15968caeeSMarri Devender Rao /* 25968caeeSMarri Devender Rao // Copyright (c) 2018 IBM Corporation 35968caeeSMarri Devender Rao // 45968caeeSMarri Devender Rao // Licensed under the Apache License, Version 2.0 (the "License"); 55968caeeSMarri Devender Rao // you may not use this file except in compliance with the License. 65968caeeSMarri Devender Rao // You may obtain a copy of the License at 75968caeeSMarri Devender Rao // 85968caeeSMarri Devender Rao // http://www.apache.org/licenses/LICENSE-2.0 95968caeeSMarri Devender Rao // 105968caeeSMarri Devender Rao // Unless required by applicable law or agreed to in writing, software 115968caeeSMarri Devender Rao // distributed under the License is distributed on an "AS IS" BASIS, 125968caeeSMarri Devender Rao // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135968caeeSMarri Devender Rao // See the License for the specific language governing permissions and 145968caeeSMarri Devender Rao // limitations under the License. 155968caeeSMarri Devender Rao */ 165968caeeSMarri Devender Rao #pragma once 175968caeeSMarri Devender Rao 185968caeeSMarri Devender Rao #include "node.hpp" 195968caeeSMarri Devender Rao 205968caeeSMarri Devender Rao #include <variant> 215968caeeSMarri Devender Rao namespace redfish 225968caeeSMarri Devender Rao { 235968caeeSMarri Devender Rao namespace certs 245968caeeSMarri Devender Rao { 255968caeeSMarri Devender Rao constexpr char const *httpsObjectPath = 265968caeeSMarri Devender Rao "/xyz/openbmc_project/certs/server/https"; 275968caeeSMarri Devender Rao constexpr char const *certInstallIntf = "xyz.openbmc_project.Certs.Install"; 285968caeeSMarri Devender Rao constexpr char const *certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 295968caeeSMarri Devender Rao constexpr char const *certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 305968caeeSMarri Devender Rao constexpr char const *dbusPropIntf = "org.freedesktop.DBus.Properties"; 315968caeeSMarri Devender Rao constexpr char const *dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 3237cce918SMarri Devender Rao constexpr char const *ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 3337cce918SMarri Devender Rao constexpr char const *httpsServiceName = 3437cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 3537cce918SMarri Devender Rao constexpr char const *ldapServiceName = 3637cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 37cfcd5f6bSMarri Devender Rao constexpr char const *authorityServiceName = 38cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 39cfcd5f6bSMarri Devender Rao constexpr char const *authorityObjectPath = 40cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 415968caeeSMarri Devender Rao } // namespace certs 425968caeeSMarri Devender Rao 435968caeeSMarri Devender Rao /** 445968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 455968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 465968caeeSMarri Devender Rao * are installed. 475968caeeSMarri Devender Rao */ 485968caeeSMarri Devender Rao class CertificateService : public Node 495968caeeSMarri Devender Rao { 505968caeeSMarri Devender Rao public: 515968caeeSMarri Devender Rao CertificateService(CrowApp &app) : 525968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/") 535968caeeSMarri Devender Rao { 545968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 555968caeeSMarri Devender Rao // sevice at https://www.dmtf.org/standards/redfish 565968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 575968caeeSMarri Devender Rao // publish Privilege details for certificate service 585968caeeSMarri Devender Rao entityPrivileges = { 595968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 605968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 615968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 625968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 635968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 645968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 655968caeeSMarri Devender Rao } 665968caeeSMarri Devender Rao 675968caeeSMarri Devender Rao private: 685968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 695968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 705968caeeSMarri Devender Rao { 715968caeeSMarri Devender Rao res.jsonValue = { 725968caeeSMarri Devender Rao {"@odata.type", "#CertificateService.v1_0_0.CertificateService"}, 735968caeeSMarri Devender Rao {"@odata.id", "/redfish/v1/CertificateService"}, 745968caeeSMarri Devender Rao {"@odata.context", 755968caeeSMarri Devender Rao "/redfish/v1/$metadata#CertificateService.CertificateService"}, 765968caeeSMarri Devender Rao {"Id", "CertificateService"}, 775968caeeSMarri Devender Rao {"Name", "Certificate Service"}, 785968caeeSMarri Devender Rao {"Description", "Actions available to manage certificates"}}; 795968caeeSMarri Devender Rao res.jsonValue["CertificateLocations"] = { 805968caeeSMarri Devender Rao {"@odata.id", 815968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}}; 825968caeeSMarri Devender Rao res.jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { 835968caeeSMarri Devender Rao {"target", "/redfish/v1/CertificateService/Actions/" 845968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate"}, 855968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 8630215816SMarri Devender Rao res.jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 8730215816SMarri Devender Rao {"target", "/redfish/v1/CertificateService/Actions/" 8830215816SMarri Devender Rao "CertificateService.GenerateCSR"}}; 895968caeeSMarri Devender Rao res.end(); 905968caeeSMarri Devender Rao } 915968caeeSMarri Devender Rao }; // CertificateService 9237cce918SMarri Devender Rao 935968caeeSMarri Devender Rao /** 945968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 955968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 965968caeeSMarri Devender Rao * @param[in] path URL 975968caeeSMarri Devender Rao * @return -1 on failure and number on success 985968caeeSMarri Devender Rao */ 995968caeeSMarri Devender Rao long getIDFromURL(const std::string_view url) 1005968caeeSMarri Devender Rao { 1015968caeeSMarri Devender Rao std::size_t found = url.rfind("/"); 1025968caeeSMarri Devender Rao if (found == std::string::npos) 1035968caeeSMarri Devender Rao { 1045968caeeSMarri Devender Rao return -1; 1055968caeeSMarri Devender Rao } 1065968caeeSMarri Devender Rao if ((found + 1) < url.length()) 1075968caeeSMarri Devender Rao { 1085968caeeSMarri Devender Rao char *endPtr; 1095968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 1105968caeeSMarri Devender Rao long value = std::strtol(str.data(), &endPtr, 10); 11137cce918SMarri Devender Rao if (endPtr != str.end()) 1125968caeeSMarri Devender Rao { 1135968caeeSMarri Devender Rao return -1; 1145968caeeSMarri Devender Rao } 1155968caeeSMarri Devender Rao return value; 1165968caeeSMarri Devender Rao } 1175968caeeSMarri Devender Rao return -1; 1185968caeeSMarri Devender Rao } 1195968caeeSMarri Devender Rao 12058eb238fSKowalski, Kamil std::string 12158eb238fSKowalski, Kamil getCertificateFromReqBody(const std::shared_ptr<AsyncResp> &asyncResp, 12258eb238fSKowalski, Kamil const crow::Request &req) 12358eb238fSKowalski, Kamil { 12458eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 12558eb238fSKowalski, Kamil 12658eb238fSKowalski, Kamil if (reqJson.is_discarded()) 12758eb238fSKowalski, Kamil { 12858eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 12958eb238fSKowalski, Kamil return req.body; 13058eb238fSKowalski, Kamil } 13158eb238fSKowalski, Kamil 13258eb238fSKowalski, Kamil std::string certificate; 13358eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 13458eb238fSKowalski, Kamil 13558eb238fSKowalski, Kamil if (!json_util::readJson(reqJson, asyncResp->res, "CertificateString", 13658eb238fSKowalski, Kamil certificate, "CertificateType", certificateType)) 13758eb238fSKowalski, Kamil { 13858eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 13958eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 14058eb238fSKowalski, Kamil return std::string(); 14158eb238fSKowalski, Kamil } 14258eb238fSKowalski, Kamil 14358eb238fSKowalski, Kamil if (*certificateType != "PEM") 14458eb238fSKowalski, Kamil { 14558eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 14658eb238fSKowalski, Kamil "CertificateType"); 14758eb238fSKowalski, Kamil return std::string(); 14858eb238fSKowalski, Kamil } 14958eb238fSKowalski, Kamil 15058eb238fSKowalski, Kamil return certificate; 15158eb238fSKowalski, Kamil } 15258eb238fSKowalski, Kamil 1535968caeeSMarri Devender Rao /** 1545968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1555968caeeSMarri Devender Rao */ 1565968caeeSMarri Devender Rao class CertificateFile 1575968caeeSMarri Devender Rao { 1585968caeeSMarri Devender Rao public: 1595968caeeSMarri Devender Rao CertificateFile() = delete; 1605968caeeSMarri Devender Rao CertificateFile(const CertificateFile &) = delete; 1615968caeeSMarri Devender Rao CertificateFile &operator=(const CertificateFile &) = delete; 1625968caeeSMarri Devender Rao CertificateFile(CertificateFile &&) = delete; 1635968caeeSMarri Devender Rao CertificateFile &operator=(CertificateFile &&) = delete; 1645968caeeSMarri Devender Rao CertificateFile(const std::string &certString) 1655968caeeSMarri Devender Rao { 1665968caeeSMarri Devender Rao char dirTemplate[] = "/tmp/Certs.XXXXXX"; 1675968caeeSMarri Devender Rao char *tempDirectory = mkdtemp(dirTemplate); 1685968caeeSMarri Devender Rao if (tempDirectory) 1695968caeeSMarri Devender Rao { 1705968caeeSMarri Devender Rao certDirectory = tempDirectory; 1715968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1725968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1735968caeeSMarri Devender Rao std::ofstream::binary | 1745968caeeSMarri Devender Rao std::ofstream::trunc); 1755968caeeSMarri Devender Rao out << certString; 1765968caeeSMarri Devender Rao out.close(); 1775968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile; 1785968caeeSMarri Devender Rao } 1795968caeeSMarri Devender Rao } 1805968caeeSMarri Devender Rao ~CertificateFile() 1815968caeeSMarri Devender Rao { 1825968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1835968caeeSMarri Devender Rao { 1845968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile; 1855968caeeSMarri Devender Rao try 1865968caeeSMarri Devender Rao { 1875968caeeSMarri Devender Rao std::filesystem::remove_all(certDirectory); 1885968caeeSMarri Devender Rao } 1895968caeeSMarri Devender Rao catch (const std::filesystem::filesystem_error &e) 1905968caeeSMarri Devender Rao { 1915968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1925968caeeSMarri Devender Rao << certDirectory; 1935968caeeSMarri Devender Rao } 1945968caeeSMarri Devender Rao } 1955968caeeSMarri Devender Rao } 1965968caeeSMarri Devender Rao std::string getCertFilePath() 1975968caeeSMarri Devender Rao { 1985968caeeSMarri Devender Rao return certificateFile; 1995968caeeSMarri Devender Rao } 2005968caeeSMarri Devender Rao 2015968caeeSMarri Devender Rao private: 2025968caeeSMarri Devender Rao std::filesystem::path certificateFile; 2035968caeeSMarri Devender Rao std::filesystem::path certDirectory; 2045968caeeSMarri Devender Rao }; 2055968caeeSMarri Devender Rao 20630215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 20730215816SMarri Devender Rao /** 20830215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 20930215816SMarri Devender Rao * 21030215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 21130215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 21230215816SMarri Devender Rao * @param[in] service D-Bus service name 21330215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 21430215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 21530215816SMarri Devender Rao * @return None 21630215816SMarri Devender Rao */ 21730215816SMarri Devender Rao static void getCSR(const std::shared_ptr<AsyncResp> &asyncResp, 21830215816SMarri Devender Rao const std::string &certURI, const std::string &service, 21930215816SMarri Devender Rao const std::string &certObjPath, 22030215816SMarri Devender Rao const std::string &csrObjPath) 22130215816SMarri Devender Rao { 22230215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 22330215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 22430215816SMarri Devender Rao << " service=" << service; 22530215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 22630215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 22730215816SMarri Devender Rao const std::string &csr) { 22830215816SMarri Devender Rao if (ec) 22930215816SMarri Devender Rao { 23030215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 23130215816SMarri Devender Rao messages::internalError(asyncResp->res); 23230215816SMarri Devender Rao return; 23330215816SMarri Devender Rao } 23430215816SMarri Devender Rao if (csr.empty()) 23530215816SMarri Devender Rao { 23630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 23730215816SMarri Devender Rao messages::internalError(asyncResp->res); 23830215816SMarri Devender Rao return; 23930215816SMarri Devender Rao } 24030215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 24130215816SMarri Devender Rao asyncResp->res.jsonValue["CertificateCollection"] = { 24230215816SMarri Devender Rao {"@odata.id", certURI}}; 24330215816SMarri Devender Rao }, 24430215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 24530215816SMarri Devender Rao } 24630215816SMarri Devender Rao 24730215816SMarri Devender Rao /** 24830215816SMarri Devender Rao * Action to Generate CSR 24930215816SMarri Devender Rao */ 25030215816SMarri Devender Rao class CertificateActionGenerateCSR : public Node 25130215816SMarri Devender Rao { 25230215816SMarri Devender Rao public: 25330215816SMarri Devender Rao CertificateActionGenerateCSR(CrowApp &app) : 25430215816SMarri Devender Rao Node(app, "/redfish/v1/CertificateService/Actions/" 25530215816SMarri Devender Rao "CertificateService.GenerateCSR/") 25630215816SMarri Devender Rao { 25730215816SMarri Devender Rao entityPrivileges = { 25830215816SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 25930215816SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 26030215816SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 26130215816SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 26230215816SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 26330215816SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 26430215816SMarri Devender Rao } 26530215816SMarri Devender Rao 26630215816SMarri Devender Rao private: 26730215816SMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 26830215816SMarri Devender Rao const std::vector<std::string> ¶ms) override 26930215816SMarri Devender Rao { 27030215816SMarri Devender Rao static const int RSA_KEY_BIT_LENGTH = 2048; 27130215816SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 27230215816SMarri Devender Rao // Required parameters 27330215816SMarri Devender Rao std::string city; 27430215816SMarri Devender Rao std::string commonName; 27530215816SMarri Devender Rao std::string country; 27630215816SMarri Devender Rao std::string organization; 27730215816SMarri Devender Rao std::string organizationalUnit; 27830215816SMarri Devender Rao std::string state; 27930215816SMarri Devender Rao nlohmann::json certificateCollection; 28030215816SMarri Devender Rao 28130215816SMarri Devender Rao // Optional parameters 28230215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 28330215816SMarri Devender Rao std::vector<std::string>(); 28430215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 28530215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 28630215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 28730215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 28830215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 28930215816SMarri Devender Rao std::optional<int64_t> optKeyBitLength = RSA_KEY_BIT_LENGTH; 29030215816SMarri Devender Rao std::optional<std::string> optKeyCurveId = "prime256v1"; 29130215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 29230215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 29330215816SMarri Devender Rao std::vector<std::string>(); 29430215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 29530215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 29630215816SMarri Devender Rao if (!json_util::readJson( 29730215816SMarri Devender Rao req, asyncResp->res, "City", city, "CommonName", commonName, 29830215816SMarri Devender Rao "ContactPerson", optContactPerson, "Country", country, 29930215816SMarri Devender Rao "Organization", organization, "OrganizationalUnit", 30030215816SMarri Devender Rao organizationalUnit, "State", state, "CertificateCollection", 30130215816SMarri Devender Rao certificateCollection, "AlternativeNames", optAlternativeNames, 30230215816SMarri Devender Rao "ChallengePassword", optChallengePassword, "Email", optEmail, 30330215816SMarri Devender Rao "GivenName", optGivenName, "Initials", optInitials, 30430215816SMarri Devender Rao "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, 30530215816SMarri Devender Rao "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 30630215816SMarri Devender Rao optKeyUsage, "Surname", optSurname, "UnstructuredName", 30730215816SMarri Devender Rao optUnstructuredName)) 30830215816SMarri Devender Rao { 30930215816SMarri Devender Rao return; 31030215816SMarri Devender Rao } 31130215816SMarri Devender Rao 31230215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 31330215816SMarri Devender Rao // password, which will likely cause bmcweb to crash on startup if this 31430215816SMarri Devender Rao // is not set on a post so not allowing the user to set value 31530215816SMarri Devender Rao if (*optChallengePassword != "") 31630215816SMarri Devender Rao { 31730215816SMarri Devender Rao messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 31830215816SMarri Devender Rao "ChallengePassword"); 31930215816SMarri Devender Rao return; 32030215816SMarri Devender Rao } 32130215816SMarri Devender Rao 32230215816SMarri Devender Rao std::string certURI; 32330215816SMarri Devender Rao if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, 32430215816SMarri Devender Rao "@odata.id", certURI)) 32530215816SMarri Devender Rao { 32630215816SMarri Devender Rao return; 32730215816SMarri Devender Rao } 32830215816SMarri Devender Rao 32930215816SMarri Devender Rao std::string objectPath; 33030215816SMarri Devender Rao std::string service; 33130215816SMarri Devender Rao if (boost::starts_with( 33230215816SMarri Devender Rao certURI, 33330215816SMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 33430215816SMarri Devender Rao { 33530215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 33630215816SMarri Devender Rao service = certs::httpsServiceName; 33730215816SMarri Devender Rao } 3383b7f0149SMarri Devender Rao else if (boost::starts_with( 3393b7f0149SMarri Devender Rao certURI, "/redfish/v1/AccountService/LDAP/Certificates")) 3403b7f0149SMarri Devender Rao { 3413b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3423b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3433b7f0149SMarri Devender Rao } 34430215816SMarri Devender Rao else 34530215816SMarri Devender Rao { 34630215816SMarri Devender Rao messages::actionParameterNotSupported( 34730215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 34830215816SMarri Devender Rao return; 34930215816SMarri Devender Rao } 35030215816SMarri Devender Rao 35130215816SMarri Devender Rao // supporting only EC and RSA algorithm 35230215816SMarri Devender Rao if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 35330215816SMarri Devender Rao { 35430215816SMarri Devender Rao messages::actionParameterNotSupported( 35530215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 35630215816SMarri Devender Rao return; 35730215816SMarri Devender Rao } 35830215816SMarri Devender Rao 35930215816SMarri Devender Rao // supporting only 2048 key bit length for RSA algorithm due to time 36030215816SMarri Devender Rao // consumed in generating private key 36130215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 36230215816SMarri Devender Rao *optKeyBitLength != RSA_KEY_BIT_LENGTH) 36330215816SMarri Devender Rao { 36430215816SMarri Devender Rao messages::propertyValueNotInList(asyncResp->res, 36530215816SMarri Devender Rao std::to_string(*optKeyBitLength), 36630215816SMarri Devender Rao "KeyBitLength"); 36730215816SMarri Devender Rao return; 36830215816SMarri Devender Rao } 36930215816SMarri Devender Rao 37030215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 37130215816SMarri Devender Rao if (boost::starts_with( 37230215816SMarri Devender Rao certURI, 37330215816SMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 37430215816SMarri Devender Rao { 37530215816SMarri Devender Rao if (optKeyUsage->size() == 0) 37630215816SMarri Devender Rao { 37730215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 37830215816SMarri Devender Rao } 37930215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 38030215816SMarri Devender Rao { 38130215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 38230215816SMarri Devender Rao { 38330215816SMarri Devender Rao messages::propertyValueNotInList( 38430215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 38530215816SMarri Devender Rao return; 38630215816SMarri Devender Rao } 38730215816SMarri Devender Rao } 38830215816SMarri Devender Rao else 38930215816SMarri Devender Rao { 39030215816SMarri Devender Rao messages::actionParameterNotSupported( 39130215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 39230215816SMarri Devender Rao return; 39330215816SMarri Devender Rao } 39430215816SMarri Devender Rao } 3953b7f0149SMarri Devender Rao else if (boost::starts_with( 3963b7f0149SMarri Devender Rao certURI, "/redfish/v1/AccountService/LDAP/Certificates")) 3973b7f0149SMarri Devender Rao { 3983b7f0149SMarri Devender Rao if (optKeyUsage->size() == 0) 3993b7f0149SMarri Devender Rao { 4003b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 4013b7f0149SMarri Devender Rao } 4023b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 4033b7f0149SMarri Devender Rao { 4043b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 4053b7f0149SMarri Devender Rao { 4063b7f0149SMarri Devender Rao messages::propertyValueNotInList( 4073b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 4083b7f0149SMarri Devender Rao return; 4093b7f0149SMarri Devender Rao } 4103b7f0149SMarri Devender Rao } 4113b7f0149SMarri Devender Rao else 4123b7f0149SMarri Devender Rao { 4133b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 4143b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 4153b7f0149SMarri Devender Rao return; 4163b7f0149SMarri Devender Rao } 4173b7f0149SMarri Devender Rao } 41830215816SMarri Devender Rao 41930215816SMarri Devender Rao // Only allow one CSR matcher at a time so setting retry time-out and 42030215816SMarri Devender Rao // timer expiry to 10 seconds for now. 42130215816SMarri Devender Rao static const int TIME_OUT = 10; 42230215816SMarri Devender Rao if (csrMatcher) 42330215816SMarri Devender Rao { 42430215816SMarri Devender Rao res.addHeader("Retry-After", std::to_string(TIME_OUT)); 42530215816SMarri Devender Rao messages::serviceTemporarilyUnavailable(asyncResp->res, 42630215816SMarri Devender Rao std::to_string(TIME_OUT)); 42730215816SMarri Devender Rao return; 42830215816SMarri Devender Rao } 42930215816SMarri Devender Rao 43030215816SMarri Devender Rao // Make this static so it survives outside this method 43130215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 43230215816SMarri Devender Rao timeout.expires_after(std::chrono::seconds(TIME_OUT)); 43330215816SMarri Devender Rao timeout.async_wait([asyncResp](const boost::system::error_code &ec) { 43430215816SMarri Devender Rao csrMatcher = nullptr; 43530215816SMarri Devender Rao if (ec) 43630215816SMarri Devender Rao { 43730215816SMarri Devender Rao // operation_aborted is expected if timer is canceled before 43830215816SMarri Devender Rao // completion. 43930215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 44030215816SMarri Devender Rao { 44130215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 44230215816SMarri Devender Rao } 44330215816SMarri Devender Rao return; 44430215816SMarri Devender Rao } 44530215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 44630215816SMarri Devender Rao messages::internalError(asyncResp->res); 44730215816SMarri Devender Rao }); 44830215816SMarri Devender Rao 44930215816SMarri Devender Rao // create a matcher to wait on CSR object 45030215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 45130215816SMarri Devender Rao std::string match("type='signal'," 45230215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 45330215816SMarri Devender Rao "path='" + 45430215816SMarri Devender Rao objectPath + 45530215816SMarri Devender Rao "'," 45630215816SMarri Devender Rao "member='InterfacesAdded'"); 45730215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 45830215816SMarri Devender Rao *crow::connections::systemBus, match, 45930215816SMarri Devender Rao [asyncResp, service, objectPath, 46030215816SMarri Devender Rao certURI](sdbusplus::message::message &m) { 461271584abSEd Tanous timeout.cancel(); 46230215816SMarri Devender Rao if (m.is_method_error()) 46330215816SMarri Devender Rao { 46430215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 46530215816SMarri Devender Rao messages::internalError(asyncResp->res); 46630215816SMarri Devender Rao return; 46730215816SMarri Devender Rao } 46830215816SMarri Devender Rao std::vector<std::pair< 46930215816SMarri Devender Rao std::string, std::vector<std::pair< 47030215816SMarri Devender Rao std::string, std::variant<std::string>>>>> 47130215816SMarri Devender Rao interfacesProperties; 47230215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 47330215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 47430215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 47530215816SMarri Devender Rao for (auto &interface : interfacesProperties) 47630215816SMarri Devender Rao { 47730215816SMarri Devender Rao if (interface.first == "xyz.openbmc_project.Certs.CSR") 47830215816SMarri Devender Rao { 47930215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 48030215816SMarri Devender Rao csrObjectPath.str); 48130215816SMarri Devender Rao break; 48230215816SMarri Devender Rao } 48330215816SMarri Devender Rao } 48430215816SMarri Devender Rao }); 48530215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 486271584abSEd Tanous [asyncResp](const boost::system::error_code &ec, 48730215816SMarri Devender Rao const std::string &path) { 48830215816SMarri Devender Rao if (ec) 48930215816SMarri Devender Rao { 49030215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message(); 49130215816SMarri Devender Rao messages::internalError(asyncResp->res); 49230215816SMarri Devender Rao return; 49330215816SMarri Devender Rao } 49430215816SMarri Devender Rao }, 49530215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 49630215816SMarri Devender Rao "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 49730215816SMarri Devender Rao commonName, *optContactPerson, country, *optEmail, *optGivenName, 49830215816SMarri Devender Rao *optInitials, *optKeyBitLength, *optKeyCurveId, 49930215816SMarri Devender Rao *optKeyPairAlgorithm, *optKeyUsage, organization, 50030215816SMarri Devender Rao organizationalUnit, state, *optSurname, *optUnstructuredName); 50130215816SMarri Devender Rao } 50230215816SMarri Devender Rao }; // CertificateActionGenerateCSR 50330215816SMarri Devender Rao 5045968caeeSMarri Devender Rao /** 5055968caeeSMarri Devender Rao * @brief Parse and update Certficate Issue/Subject property 5065968caeeSMarri Devender Rao * 5075968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5085968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 5095968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 5105968caeeSMarri Devender Rao * @return None 5115968caeeSMarri Devender Rao */ 5125968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json &out, 5135968caeeSMarri Devender Rao const std::string_view value) 5145968caeeSMarri Devender Rao { 5155968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 5165968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 5175968caeeSMarri Devender Rao while (i != value.end()) 5185968caeeSMarri Devender Rao { 5195968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 5205968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 5215968caeeSMarri Devender Rao { 5225968caeeSMarri Devender Rao i++; 5235968caeeSMarri Devender Rao } 5245968caeeSMarri Devender Rao if (i == value.end()) 5255968caeeSMarri Devender Rao { 5265968caeeSMarri Devender Rao break; 5275968caeeSMarri Devender Rao } 528271584abSEd Tanous const std::string_view key(tokenBegin, 529271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5305968caeeSMarri Devender Rao i++; 5315968caeeSMarri Devender Rao tokenBegin = i; 5325968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 5335968caeeSMarri Devender Rao { 5345968caeeSMarri Devender Rao i++; 5355968caeeSMarri Devender Rao } 536271584abSEd Tanous const std::string_view val(tokenBegin, 537271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5385968caeeSMarri Devender Rao if (key == "L") 5395968caeeSMarri Devender Rao { 5405968caeeSMarri Devender Rao out["City"] = val; 5415968caeeSMarri Devender Rao } 5425968caeeSMarri Devender Rao else if (key == "CN") 5435968caeeSMarri Devender Rao { 5445968caeeSMarri Devender Rao out["CommonName"] = val; 5455968caeeSMarri Devender Rao } 5465968caeeSMarri Devender Rao else if (key == "C") 5475968caeeSMarri Devender Rao { 5485968caeeSMarri Devender Rao out["Country"] = val; 5495968caeeSMarri Devender Rao } 5505968caeeSMarri Devender Rao else if (key == "O") 5515968caeeSMarri Devender Rao { 5525968caeeSMarri Devender Rao out["Organization"] = val; 5535968caeeSMarri Devender Rao } 5545968caeeSMarri Devender Rao else if (key == "OU") 5555968caeeSMarri Devender Rao { 5565968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5575968caeeSMarri Devender Rao } 5585968caeeSMarri Devender Rao else if (key == "ST") 5595968caeeSMarri Devender Rao { 5605968caeeSMarri Devender Rao out["State"] = val; 5615968caeeSMarri Devender Rao } 5625968caeeSMarri Devender Rao // skip comma character 5635968caeeSMarri Devender Rao if (i != value.end()) 5645968caeeSMarri Devender Rao { 5655968caeeSMarri Devender Rao i++; 5665968caeeSMarri Devender Rao } 5675968caeeSMarri Devender Rao } 5685968caeeSMarri Devender Rao } 5695968caeeSMarri Devender Rao 5705968caeeSMarri Devender Rao /** 5715968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5725968caeeSMarri Devender Rao * message 5735968caeeSMarri Devender Rao * 5745968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5755968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5765968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5775968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5785968caeeSMarri Devender Rao * @param[in] name name of the certificate 5795968caeeSMarri Devender Rao * @return None 5805968caeeSMarri Devender Rao */ 5815968caeeSMarri Devender Rao static void getCertificateProperties( 5825968caeeSMarri Devender Rao const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath, 58337cce918SMarri Devender Rao const std::string &service, long certId, const std::string &certURL, 58437cce918SMarri Devender Rao const std::string &name) 5855968caeeSMarri Devender Rao { 5865968caeeSMarri Devender Rao using PropertyType = 5875968caeeSMarri Devender Rao std::variant<std::string, uint64_t, std::vector<std::string>>; 5885968caeeSMarri Devender Rao using PropertiesMap = boost::container::flat_map<std::string, PropertyType>; 5895968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5905968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5915968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 59237cce918SMarri Devender Rao [asyncResp, certURL, certId, name](const boost::system::error_code ec, 5935968caeeSMarri Devender Rao const PropertiesMap &properties) { 5945968caeeSMarri Devender Rao if (ec) 5955968caeeSMarri Devender Rao { 5965968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5978aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5988aae75adSMarri Devender Rao std::to_string(certId)); 5995968caeeSMarri Devender Rao return; 6005968caeeSMarri Devender Rao } 6015968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 6025968caeeSMarri Devender Rao {"@odata.id", certURL}, 6035968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 6045968caeeSMarri Devender Rao {"@odata.context", 6055968caeeSMarri Devender Rao "/redfish/v1/$metadata#Certificate.Certificate"}, 6065968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 6075968caeeSMarri Devender Rao {"Name", name}, 6085968caeeSMarri Devender Rao {"Description", name}}; 6095968caeeSMarri Devender Rao for (const auto &property : properties) 6105968caeeSMarri Devender Rao { 6115968caeeSMarri Devender Rao if (property.first == "CertificateString") 6125968caeeSMarri Devender Rao { 6135968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 6145968caeeSMarri Devender Rao const std::string *value = 6155968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6165968caeeSMarri Devender Rao if (value) 6175968caeeSMarri Devender Rao { 61837cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 6195968caeeSMarri Devender Rao } 6205968caeeSMarri Devender Rao } 6215968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 6225968caeeSMarri Devender Rao { 6235968caeeSMarri Devender Rao nlohmann::json &keyUsage = 6245968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 6255968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6265968caeeSMarri Devender Rao const std::vector<std::string> *value = 62737cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 6285968caeeSMarri Devender Rao if (value) 6295968caeeSMarri Devender Rao { 6305968caeeSMarri Devender Rao for (const std::string &usage : *value) 6315968caeeSMarri Devender Rao { 6325968caeeSMarri Devender Rao keyUsage.push_back(usage); 6335968caeeSMarri Devender Rao } 6345968caeeSMarri Devender Rao } 6355968caeeSMarri Devender Rao } 6365968caeeSMarri Devender Rao else if (property.first == "Issuer") 6375968caeeSMarri Devender Rao { 6385968caeeSMarri Devender Rao const std::string *value = 6395968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6405968caeeSMarri Devender Rao if (value) 6415968caeeSMarri Devender Rao { 6425968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6435968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6445968caeeSMarri Devender Rao } 6455968caeeSMarri Devender Rao } 6465968caeeSMarri Devender Rao else if (property.first == "Subject") 6475968caeeSMarri Devender Rao { 6485968caeeSMarri Devender Rao const std::string *value = 6495968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6505968caeeSMarri Devender Rao if (value) 6515968caeeSMarri Devender Rao { 6525968caeeSMarri Devender Rao updateCertIssuerOrSubject( 65337cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6545968caeeSMarri Devender Rao } 6555968caeeSMarri Devender Rao } 6565968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6575968caeeSMarri Devender Rao { 6585968caeeSMarri Devender Rao const uint64_t *value = 6595968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6605968caeeSMarri Devender Rao if (value) 6615968caeeSMarri Devender Rao { 66237cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6635968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6645968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6655968caeeSMarri Devender Rao } 6665968caeeSMarri Devender Rao } 6675968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6685968caeeSMarri Devender Rao { 6695968caeeSMarri Devender Rao const uint64_t *value = 6705968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6715968caeeSMarri Devender Rao if (value) 6725968caeeSMarri Devender Rao { 67337cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6745968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6755968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6765968caeeSMarri Devender Rao } 6775968caeeSMarri Devender Rao } 6785968caeeSMarri Devender Rao } 6795968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6805968caeeSMarri Devender Rao }, 6815968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6825968caeeSMarri Devender Rao certs::certPropIntf); 6835968caeeSMarri Devender Rao } 6845968caeeSMarri Devender Rao 6855968caeeSMarri Devender Rao using GetObjectType = 6865968caeeSMarri Devender Rao std::vector<std::pair<std::string, std::vector<std::string>>>; 6875968caeeSMarri Devender Rao 6885968caeeSMarri Devender Rao /** 6895968caeeSMarri Devender Rao * Action to replace an existing certificate 6905968caeeSMarri Devender Rao */ 6915968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node 6925968caeeSMarri Devender Rao { 6935968caeeSMarri Devender Rao public: 6945968caeeSMarri Devender Rao CertificateActionsReplaceCertificate(CrowApp &app) : 6955968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/Actions/" 6965968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate/") 6975968caeeSMarri Devender Rao { 6985968caeeSMarri Devender Rao entityPrivileges = { 6995968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 7005968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 7015968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 7025968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 7035968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 7045968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 7055968caeeSMarri Devender Rao } 7065968caeeSMarri Devender Rao 7075968caeeSMarri Devender Rao private: 7085968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 7095968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 7105968caeeSMarri Devender Rao { 7115968caeeSMarri Devender Rao std::string certificate; 7125968caeeSMarri Devender Rao nlohmann::json certificateUri; 7135968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 7145968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 7155968caeeSMarri Devender Rao if (!json_util::readJson(req, asyncResp->res, "CertificateString", 7165968caeeSMarri Devender Rao certificate, "CertificateUri", certificateUri, 7175968caeeSMarri Devender Rao "CertificateType", certificateType)) 7185968caeeSMarri Devender Rao { 7195968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 7205968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 7215968caeeSMarri Devender Rao return; 7225968caeeSMarri Devender Rao } 7235968caeeSMarri Devender Rao 7245968caeeSMarri Devender Rao if (!certificateType) 7255968caeeSMarri Devender Rao { 7265968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 7275968caeeSMarri Devender Rao return; 7285968caeeSMarri Devender Rao } 7295968caeeSMarri Devender Rao if (certificateType != "PEM") 7305968caeeSMarri Devender Rao { 7315968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7325968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7335968caeeSMarri Devender Rao return; 7345968caeeSMarri Devender Rao } 7355968caeeSMarri Devender Rao 7365968caeeSMarri Devender Rao std::string certURI; 7375968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7385968caeeSMarri Devender Rao "@odata.id", certURI)) 7395968caeeSMarri Devender Rao { 7405968caeeSMarri Devender Rao messages::actionParameterMissing( 7415968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7425968caeeSMarri Devender Rao return; 7435968caeeSMarri Devender Rao } 7445968caeeSMarri Devender Rao 7455968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7465968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7475968caeeSMarri Devender Rao if (id < 0) 7485968caeeSMarri Devender Rao { 7495968caeeSMarri Devender Rao messages::actionParameterValueFormatError(asyncResp->res, certURI, 7505968caeeSMarri Devender Rao "CertificateUri", 7515968caeeSMarri Devender Rao "ReplaceCertificate"); 7525968caeeSMarri Devender Rao return; 7535968caeeSMarri Devender Rao } 7545968caeeSMarri Devender Rao std::string objectPath; 7555968caeeSMarri Devender Rao std::string name; 75637cce918SMarri Devender Rao std::string service; 7575968caeeSMarri Devender Rao if (boost::starts_with( 7585968caeeSMarri Devender Rao certURI, 7595968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 7605968caeeSMarri Devender Rao { 7615968caeeSMarri Devender Rao objectPath = 7625968caeeSMarri Devender Rao std::string(certs::httpsObjectPath) + "/" + std::to_string(id); 7635968caeeSMarri Devender Rao name = "HTTPS certificate"; 76437cce918SMarri Devender Rao service = certs::httpsServiceName; 76537cce918SMarri Devender Rao } 76637cce918SMarri Devender Rao else if (boost::starts_with( 76737cce918SMarri Devender Rao certURI, "/redfish/v1/AccountService/LDAP/Certificates/")) 76837cce918SMarri Devender Rao { 76937cce918SMarri Devender Rao objectPath = 77037cce918SMarri Devender Rao std::string(certs::ldapObjectPath) + "/" + std::to_string(id); 77137cce918SMarri Devender Rao name = "LDAP certificate"; 77237cce918SMarri Devender Rao service = certs::ldapServiceName; 7735968caeeSMarri Devender Rao } 774cfcd5f6bSMarri Devender Rao else if (boost::starts_with( 775cfcd5f6bSMarri Devender Rao certURI, 776cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/")) 777cfcd5f6bSMarri Devender Rao { 778cfcd5f6bSMarri Devender Rao objectPath = std::string(certs::authorityObjectPath) + "/" + 779cfcd5f6bSMarri Devender Rao std::to_string(id); 780cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 781cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 782cfcd5f6bSMarri Devender Rao } 7835968caeeSMarri Devender Rao else 7845968caeeSMarri Devender Rao { 7855968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7865968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7875968caeeSMarri Devender Rao return; 7885968caeeSMarri Devender Rao } 7895968caeeSMarri Devender Rao 7905968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7915968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7925968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 79337cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7945968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7955968caeeSMarri Devender Rao if (ec) 7965968caeeSMarri Devender Rao { 7975968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 7988aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7998aae75adSMarri Devender Rao std::to_string(id)); 8005968caeeSMarri Devender Rao return; 8015968caeeSMarri Devender Rao } 80237cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 8035968caeeSMarri Devender Rao certURI, name); 8045968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 8055968caeeSMarri Devender Rao << certFile->getCertFilePath(); 8065968caeeSMarri Devender Rao }, 8075968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 8085968caeeSMarri Devender Rao certFile->getCertFilePath()); 8095968caeeSMarri Devender Rao } 8105968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate 8115968caeeSMarri Devender Rao 8125968caeeSMarri Devender Rao /** 8135968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 8145968caeeSMarri Devender Rao * of a component, account or service. 8155968caeeSMarri Devender Rao */ 8165968caeeSMarri Devender Rao class HTTPSCertificate : public Node 8175968caeeSMarri Devender Rao { 8185968caeeSMarri Devender Rao public: 8195968caeeSMarri Devender Rao template <typename CrowApp> 8205968caeeSMarri Devender Rao HTTPSCertificate(CrowApp &app) : 8215968caeeSMarri Devender Rao Node(app, 8225968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" 8235968caeeSMarri Devender Rao "<str>/", 8245968caeeSMarri Devender Rao std::string()) 8255968caeeSMarri Devender Rao { 8265968caeeSMarri Devender Rao entityPrivileges = { 8275968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 8285968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 8295968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 8305968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 8315968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 8325968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 8335968caeeSMarri Devender Rao } 8345968caeeSMarri Devender Rao 8355968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 8365968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 8375968caeeSMarri Devender Rao { 8385968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 8395968caeeSMarri Devender Rao if (params.size() != 1) 8405968caeeSMarri Devender Rao { 8415968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8425968caeeSMarri Devender Rao return; 8435968caeeSMarri Devender Rao } 8445968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8455968caeeSMarri Devender Rao 8465968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id); 8475968caeeSMarri Devender Rao std::string certURL = 8485968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8495968caeeSMarri Devender Rao std::to_string(id); 8505968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8515968caeeSMarri Devender Rao objectPath += "/"; 8525968caeeSMarri Devender Rao objectPath += std::to_string(id); 85337cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName, 85437cce918SMarri Devender Rao id, certURL, "HTTPS Certificate"); 8555968caeeSMarri Devender Rao } 8565968caeeSMarri Devender Rao 8575968caeeSMarri Devender Rao }; // namespace redfish 8585968caeeSMarri Devender Rao 8595968caeeSMarri Devender Rao /** 8605968caeeSMarri Devender Rao * Collection of HTTPS certificates 8615968caeeSMarri Devender Rao */ 8625968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node 8635968caeeSMarri Devender Rao { 8645968caeeSMarri Devender Rao public: 8655968caeeSMarri Devender Rao template <typename CrowApp> 8665968caeeSMarri Devender Rao HTTPSCertificateCollection(CrowApp &app) : 8675968caeeSMarri Devender Rao Node(app, 8685968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 8695968caeeSMarri Devender Rao { 8705968caeeSMarri Devender Rao entityPrivileges = { 8715968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 8725968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 8735968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 8745968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 8755968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 8765968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 8775968caeeSMarri Devender Rao } 8785968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 8795968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 8805968caeeSMarri Devender Rao { 8815968caeeSMarri Devender Rao res.jsonValue = { 8825968caeeSMarri Devender Rao {"@odata.id", 8835968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 8845968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 8855968caeeSMarri Devender Rao {"@odata.context", 8865968caeeSMarri Devender Rao "/redfish/v1/" 8875968caeeSMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 8885968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 8895968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 8905968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 8915968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8925968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 8935968caeeSMarri Devender Rao const ManagedObjectType &certs) { 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 } 90037cce918SMarri Devender Rao nlohmann::json &members = asyncResp->res.jsonValue["Members"]; 9015968caeeSMarri Devender Rao members = nlohmann::json::array(); 9025968caeeSMarri Devender Rao for (const auto &cert : certs) 9035968caeeSMarri Devender Rao { 9045968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 90537cce918SMarri Devender Rao if (id >= 0) 9065968caeeSMarri Devender Rao { 9075968caeeSMarri Devender Rao members.push_back( 9085968caeeSMarri Devender Rao {{"@odata.id", 9095968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/" 9105968caeeSMarri Devender Rao "NetworkProtocol/HTTPS/Certificates/" + 9115968caeeSMarri Devender Rao std::to_string(id)}}); 9125968caeeSMarri Devender Rao } 9135968caeeSMarri Devender Rao } 9145968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 9155968caeeSMarri Devender Rao members.size(); 9165968caeeSMarri Devender Rao }, 91737cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 91837cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 9195968caeeSMarri Devender Rao } 9205968caeeSMarri Devender Rao 9215968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 9225968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 9235968caeeSMarri Devender Rao { 9245968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 9255968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 9265968caeeSMarri Devender Rao asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"}, 9275968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 9285968caeeSMarri Devender Rao 92958eb238fSKowalski, Kamil std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 93058eb238fSKowalski, Kamil 93158eb238fSKowalski, Kamil if (certFileBody.empty()) 93258eb238fSKowalski, Kamil { 933*a08752f5SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 934*a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 93558eb238fSKowalski, Kamil return; 93658eb238fSKowalski, Kamil } 93758eb238fSKowalski, Kamil 9385968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 93958eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 9405968caeeSMarri Devender Rao 9415968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 942656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 943656ec7e3SZbigniew Kurzynski const std::string &objectPath) { 9445968caeeSMarri Devender Rao if (ec) 9455968caeeSMarri Devender Rao { 9465968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 9475968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9485968caeeSMarri Devender Rao return; 9495968caeeSMarri Devender Rao } 950656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 951656ec7e3SZbigniew Kurzynski if (certId < 0) 952656ec7e3SZbigniew Kurzynski { 953656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 954656ec7e3SZbigniew Kurzynski << objectPath; 955656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 956656ec7e3SZbigniew Kurzynski return; 957656ec7e3SZbigniew Kurzynski } 9585968caeeSMarri Devender Rao std::string certURL = 9595968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/" 9605968caeeSMarri Devender Rao "Certificates/" + 9615968caeeSMarri Devender Rao std::to_string(certId); 96237cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 96337cce918SMarri Devender Rao certs::httpsServiceName, certId, 9645968caeeSMarri Devender Rao certURL, "HTTPS Certificate"); 9655968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9665968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9675968caeeSMarri Devender Rao }, 96837cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 96937cce918SMarri Devender Rao certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9705968caeeSMarri Devender Rao } 9715968caeeSMarri Devender Rao }; // HTTPSCertificateCollection 9725968caeeSMarri Devender Rao 9735968caeeSMarri Devender Rao /** 9745968caeeSMarri Devender Rao * The certificate location schema defines a resource that an administrator 9755968caeeSMarri Devender Rao * can use in order to locate all certificates installed on a given service. 9765968caeeSMarri Devender Rao */ 9775968caeeSMarri Devender Rao class CertificateLocations : public Node 9785968caeeSMarri Devender Rao { 9795968caeeSMarri Devender Rao public: 9805968caeeSMarri Devender Rao template <typename CrowApp> 9815968caeeSMarri Devender Rao CertificateLocations(CrowApp &app) : 9825968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/CertificateLocations/") 9835968caeeSMarri Devender Rao { 9845968caeeSMarri Devender Rao entityPrivileges = { 9855968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 9865968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 9875968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 9885968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 9895968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 9905968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9915968caeeSMarri Devender Rao } 9925968caeeSMarri Devender Rao 9935968caeeSMarri Devender Rao private: 9945968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 9955968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 9965968caeeSMarri Devender Rao { 9975968caeeSMarri Devender Rao res.jsonValue = { 9985968caeeSMarri Devender Rao {"@odata.id", 9995968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}, 10005968caeeSMarri Devender Rao {"@odata.type", 10015968caeeSMarri Devender Rao "#CertificateLocations.v1_0_0.CertificateLocations"}, 10025968caeeSMarri Devender Rao {"@odata.context", 10035968caeeSMarri Devender Rao "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"}, 10045968caeeSMarri Devender Rao {"Name", "Certificate Locations"}, 10055968caeeSMarri Devender Rao {"Id", "CertificateLocations"}, 10065968caeeSMarri Devender Rao {"Description", 10075968caeeSMarri Devender Rao "Defines a resource that an administrator can use in order to " 10085968caeeSMarri Devender Rao "locate all certificates installed on a given service"}}; 10095968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 10105968caeeSMarri Devender Rao nlohmann::json &links = 10115968caeeSMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 10125968caeeSMarri Devender Rao links = nlohmann::json::array(); 10135968caeeSMarri Devender Rao getCertificateLocations( 10145968caeeSMarri Devender Rao asyncResp, 10155968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 101637cce918SMarri Devender Rao certs::httpsObjectPath, certs::httpsServiceName); 101737cce918SMarri Devender Rao getCertificateLocations(asyncResp, 101837cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/", 101937cce918SMarri Devender Rao certs::ldapObjectPath, certs::ldapServiceName); 1020cfcd5f6bSMarri Devender Rao getCertificateLocations( 1021cfcd5f6bSMarri Devender Rao asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", 1022cfcd5f6bSMarri Devender Rao certs::authorityObjectPath, certs::authorityServiceName); 102337cce918SMarri Devender Rao } 102437cce918SMarri Devender Rao /** 102537cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 102637cce918SMarri Devender Rao * response 102737cce918SMarri Devender Rao * 102837cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 102937cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 103037cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 103137cce918SMarri Devender Rao * @return None 103237cce918SMarri Devender Rao */ 103337cce918SMarri Devender Rao void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp, 103437cce918SMarri Devender Rao const std::string &certURL, 103537cce918SMarri Devender Rao const std::string &path, 103637cce918SMarri Devender Rao const std::string &service) 103737cce918SMarri Devender Rao { 103837cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 103937cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 104037cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 104137cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 104237cce918SMarri Devender Rao const ManagedObjectType &certs) { 104337cce918SMarri Devender Rao if (ec) 104437cce918SMarri Devender Rao { 104537cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 104637cce918SMarri Devender Rao messages::internalError(asyncResp->res); 104737cce918SMarri Devender Rao return; 104837cce918SMarri Devender Rao } 104937cce918SMarri Devender Rao nlohmann::json &links = 105037cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 105137cce918SMarri Devender Rao for (auto &cert : certs) 105237cce918SMarri Devender Rao { 105337cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 105437cce918SMarri Devender Rao if (id >= 0) 105537cce918SMarri Devender Rao { 105637cce918SMarri Devender Rao links.push_back( 105737cce918SMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 105837cce918SMarri Devender Rao } 105937cce918SMarri Devender Rao } 106037cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 106137cce918SMarri Devender Rao links.size(); 106237cce918SMarri Devender Rao }, 106337cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 10645968caeeSMarri Devender Rao } 10655968caeeSMarri Devender Rao }; // CertificateLocations 106637cce918SMarri Devender Rao 106737cce918SMarri Devender Rao /** 106837cce918SMarri Devender Rao * Collection of LDAP certificates 106937cce918SMarri Devender Rao */ 107037cce918SMarri Devender Rao class LDAPCertificateCollection : public Node 107137cce918SMarri Devender Rao { 107237cce918SMarri Devender Rao public: 107337cce918SMarri Devender Rao template <typename CrowApp> 107437cce918SMarri Devender Rao LDAPCertificateCollection(CrowApp &app) : 107537cce918SMarri Devender Rao Node(app, "/redfish/v1/AccountService/LDAP/Certificates/") 107637cce918SMarri Devender Rao { 107737cce918SMarri Devender Rao entityPrivileges = { 107837cce918SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 107937cce918SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 108037cce918SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 108137cce918SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 108237cce918SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 108337cce918SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 108437cce918SMarri Devender Rao } 108537cce918SMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 108637cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 108737cce918SMarri Devender Rao { 108837cce918SMarri Devender Rao res.jsonValue = { 108937cce918SMarri Devender Rao {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, 109037cce918SMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 109137cce918SMarri Devender Rao {"@odata.context", 109237cce918SMarri Devender Rao "/redfish/v1/" 109337cce918SMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 109437cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 109537cce918SMarri Devender Rao {"Description", "A Collection of LDAP certificate instances"}}; 109637cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 109737cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 109837cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 109937cce918SMarri Devender Rao const ManagedObjectType &certs) { 110037cce918SMarri Devender Rao if (ec) 110137cce918SMarri Devender Rao { 110237cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 110337cce918SMarri Devender Rao messages::internalError(asyncResp->res); 110437cce918SMarri Devender Rao return; 110537cce918SMarri Devender Rao } 110637cce918SMarri Devender Rao nlohmann::json &members = asyncResp->res.jsonValue["Members"]; 110737cce918SMarri Devender Rao members = nlohmann::json::array(); 110837cce918SMarri Devender Rao for (const auto &cert : certs) 110937cce918SMarri Devender Rao { 111037cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 111137cce918SMarri Devender Rao if (id >= 0) 111237cce918SMarri Devender Rao { 111337cce918SMarri Devender Rao members.push_back( 111437cce918SMarri Devender Rao {{"@odata.id", "/redfish/v1/AccountService/" 111537cce918SMarri Devender Rao "LDAP/Certificates/" + 111637cce918SMarri Devender Rao std::to_string(id)}}); 111737cce918SMarri Devender Rao } 111837cce918SMarri Devender Rao } 111937cce918SMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 112037cce918SMarri Devender Rao members.size(); 112137cce918SMarri Devender Rao }, 112237cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 112337cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 112437cce918SMarri Devender Rao } 112537cce918SMarri Devender Rao 112637cce918SMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 112737cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 112837cce918SMarri Devender Rao { 112937cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 113058eb238fSKowalski, Kamil std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 113158eb238fSKowalski, Kamil 113258eb238fSKowalski, Kamil if (certFileBody.empty()) 113358eb238fSKowalski, Kamil { 1134*a08752f5SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1135*a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 113658eb238fSKowalski, Kamil return; 113758eb238fSKowalski, Kamil } 113858eb238fSKowalski, Kamil 113958eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 114058eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 114158eb238fSKowalski, Kamil 114237cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1143656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1144656ec7e3SZbigniew Kurzynski const std::string &objectPath) { 114537cce918SMarri Devender Rao if (ec) 114637cce918SMarri Devender Rao { 114737cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 114837cce918SMarri Devender Rao messages::internalError(asyncResp->res); 114937cce918SMarri Devender Rao return; 115037cce918SMarri Devender Rao } 1151656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1152656ec7e3SZbigniew Kurzynski if (certId < 0) 1153656ec7e3SZbigniew Kurzynski { 1154656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1155656ec7e3SZbigniew Kurzynski << objectPath; 1156656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1157656ec7e3SZbigniew Kurzynski return; 1158656ec7e3SZbigniew Kurzynski } 115937cce918SMarri Devender Rao std::string certURL = 116037cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 116137cce918SMarri Devender Rao std::to_string(certId); 116237cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 116337cce918SMarri Devender Rao certs::ldapServiceName, certId, 116437cce918SMarri Devender Rao certURL, "LDAP Certificate"); 116537cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 116637cce918SMarri Devender Rao << certFile->getCertFilePath(); 116737cce918SMarri Devender Rao }, 116837cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 116937cce918SMarri Devender Rao certs::certInstallIntf, "Install", certFile->getCertFilePath()); 117037cce918SMarri Devender Rao } 117137cce918SMarri Devender Rao }; // LDAPCertificateCollection 117237cce918SMarri Devender Rao 117337cce918SMarri Devender Rao /** 117437cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 117537cce918SMarri Devender Rao * of a component, account or service. 117637cce918SMarri Devender Rao */ 117737cce918SMarri Devender Rao class LDAPCertificate : public Node 117837cce918SMarri Devender Rao { 117937cce918SMarri Devender Rao public: 118037cce918SMarri Devender Rao template <typename CrowApp> 118137cce918SMarri Devender Rao LDAPCertificate(CrowApp &app) : 118237cce918SMarri Devender Rao Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/", 118337cce918SMarri Devender Rao std::string()) 118437cce918SMarri Devender Rao { 118537cce918SMarri Devender Rao entityPrivileges = { 118637cce918SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 118737cce918SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 118837cce918SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 118937cce918SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 119037cce918SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 119137cce918SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 119237cce918SMarri Devender Rao } 119337cce918SMarri Devender Rao 119437cce918SMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 119537cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 119637cce918SMarri Devender Rao { 119737cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 119837cce918SMarri Devender Rao long id = getIDFromURL(req.url); 119937cce918SMarri Devender Rao if (id < 0) 120037cce918SMarri Devender Rao { 120137cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 120237cce918SMarri Devender Rao messages::internalError(asyncResp->res); 120337cce918SMarri Devender Rao return; 120437cce918SMarri Devender Rao } 120537cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id); 120637cce918SMarri Devender Rao std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" + 120737cce918SMarri Devender Rao std::to_string(id); 120837cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 120937cce918SMarri Devender Rao objectPath += "/"; 121037cce918SMarri Devender Rao objectPath += std::to_string(id); 121137cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, 121237cce918SMarri Devender Rao id, certURL, "LDAP Certificate"); 121337cce918SMarri Devender Rao } 121437cce918SMarri Devender Rao }; // LDAPCertificate 1215cfcd5f6bSMarri Devender Rao /** 1216cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1217cfcd5f6bSMarri Devender Rao */ 1218cfcd5f6bSMarri Devender Rao class TrustStoreCertificateCollection : public Node 1219cfcd5f6bSMarri Devender Rao { 1220cfcd5f6bSMarri Devender Rao public: 1221cfcd5f6bSMarri Devender Rao template <typename CrowApp> 1222cfcd5f6bSMarri Devender Rao TrustStoreCertificateCollection(CrowApp &app) : 1223cfcd5f6bSMarri Devender Rao Node(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1224cfcd5f6bSMarri Devender Rao { 1225cfcd5f6bSMarri Devender Rao entityPrivileges = { 1226cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 1227cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 1228cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1229cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1230cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1231cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1232cfcd5f6bSMarri Devender Rao } 1233cfcd5f6bSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 1234cfcd5f6bSMarri Devender Rao const std::vector<std::string> ¶ms) override 1235cfcd5f6bSMarri Devender Rao { 1236cfcd5f6bSMarri Devender Rao res.jsonValue = { 1237cfcd5f6bSMarri Devender Rao {"@odata.id", "/redfish/v1/Managers/bmc/Truststore/Certificates/"}, 1238cfcd5f6bSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 1239cfcd5f6bSMarri Devender Rao {"@odata.context", 1240cfcd5f6bSMarri Devender Rao "/redfish/v1/" 1241cfcd5f6bSMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 1242cfcd5f6bSMarri Devender Rao {"Name", "TrustStore Certificates Collection"}, 1243cfcd5f6bSMarri Devender Rao {"Description", 1244cfcd5f6bSMarri Devender Rao "A Collection of TrustStore certificate instances"}}; 1245cfcd5f6bSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 1246cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1247cfcd5f6bSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1248cfcd5f6bSMarri Devender Rao const ManagedObjectType &certs) { 1249cfcd5f6bSMarri Devender Rao if (ec) 1250cfcd5f6bSMarri Devender Rao { 1251cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1252cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1253cfcd5f6bSMarri Devender Rao return; 1254cfcd5f6bSMarri Devender Rao } 1255cfcd5f6bSMarri Devender Rao nlohmann::json &members = asyncResp->res.jsonValue["Members"]; 1256cfcd5f6bSMarri Devender Rao members = nlohmann::json::array(); 1257cfcd5f6bSMarri Devender Rao for (const auto &cert : certs) 1258cfcd5f6bSMarri Devender Rao { 1259cfcd5f6bSMarri Devender Rao long id = getIDFromURL(cert.first.str); 1260cfcd5f6bSMarri Devender Rao if (id >= 0) 1261cfcd5f6bSMarri Devender Rao { 1262cfcd5f6bSMarri Devender Rao members.push_back( 1263cfcd5f6bSMarri Devender Rao {{"@odata.id", "/redfish/v1/Managers/bmc/" 1264cfcd5f6bSMarri Devender Rao "Truststore/Certificates/" + 1265cfcd5f6bSMarri Devender Rao std::to_string(id)}}); 1266cfcd5f6bSMarri Devender Rao } 1267cfcd5f6bSMarri Devender Rao } 1268cfcd5f6bSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 1269cfcd5f6bSMarri Devender Rao members.size(); 1270cfcd5f6bSMarri Devender Rao }, 1271cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1272cfcd5f6bSMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 1273cfcd5f6bSMarri Devender Rao } 1274cfcd5f6bSMarri Devender Rao 1275cfcd5f6bSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 1276cfcd5f6bSMarri Devender Rao const std::vector<std::string> ¶ms) override 1277cfcd5f6bSMarri Devender Rao { 1278cfcd5f6bSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 1279*a08752f5SZbigniew Kurzynski std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 1280*a08752f5SZbigniew Kurzynski 1281*a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1282*a08752f5SZbigniew Kurzynski { 1283*a08752f5SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1284*a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1285*a08752f5SZbigniew Kurzynski return; 1286*a08752f5SZbigniew Kurzynski } 1287*a08752f5SZbigniew Kurzynski 1288*a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1289*a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1290cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1291656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1292656ec7e3SZbigniew Kurzynski const std::string &objectPath) { 1293cfcd5f6bSMarri Devender Rao if (ec) 1294cfcd5f6bSMarri Devender Rao { 1295cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1296cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1297cfcd5f6bSMarri Devender Rao return; 1298cfcd5f6bSMarri Devender Rao } 1299656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1300656ec7e3SZbigniew Kurzynski if (certId < 0) 1301656ec7e3SZbigniew Kurzynski { 1302656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1303656ec7e3SZbigniew Kurzynski << objectPath; 1304656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1305656ec7e3SZbigniew Kurzynski return; 1306656ec7e3SZbigniew Kurzynski } 1307cfcd5f6bSMarri Devender Rao std::string certURL = "/redfish/v1/Managers/bmc/" 1308cfcd5f6bSMarri Devender Rao "Truststore/Certificates/" + 1309cfcd5f6bSMarri Devender Rao std::to_string(certId); 1310656ec7e3SZbigniew Kurzynski 1311cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 1312cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certId, 1313cfcd5f6bSMarri Devender Rao certURL, "TrustStore Certificate"); 1314cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1315cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1316cfcd5f6bSMarri Devender Rao }, 1317cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1318cfcd5f6bSMarri Devender Rao certs::certInstallIntf, "Install", certFile->getCertFilePath()); 1319cfcd5f6bSMarri Devender Rao } 1320cfcd5f6bSMarri Devender Rao }; // TrustStoreCertificateCollection 1321cfcd5f6bSMarri Devender Rao 1322cfcd5f6bSMarri Devender Rao /** 1323cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1324cfcd5f6bSMarri Devender Rao * of a component, account or service. 1325cfcd5f6bSMarri Devender Rao */ 1326cfcd5f6bSMarri Devender Rao class TrustStoreCertificate : public Node 1327cfcd5f6bSMarri Devender Rao { 1328cfcd5f6bSMarri Devender Rao public: 1329cfcd5f6bSMarri Devender Rao template <typename CrowApp> 1330cfcd5f6bSMarri Devender Rao TrustStoreCertificate(CrowApp &app) : 1331cfcd5f6bSMarri Devender Rao Node(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/", 1332cfcd5f6bSMarri Devender Rao std::string()) 1333cfcd5f6bSMarri Devender Rao { 1334cfcd5f6bSMarri Devender Rao entityPrivileges = { 1335cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 1336cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 1337cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1338cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1339cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1340cfcd5f6bSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1341cfcd5f6bSMarri Devender Rao } 1342cfcd5f6bSMarri Devender Rao 1343cfcd5f6bSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 1344cfcd5f6bSMarri Devender Rao const std::vector<std::string> ¶ms) override 1345cfcd5f6bSMarri Devender Rao { 1346cfcd5f6bSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 1347cfcd5f6bSMarri Devender Rao long id = getIDFromURL(req.url); 1348cfcd5f6bSMarri Devender Rao if (id < 0) 1349cfcd5f6bSMarri Devender Rao { 1350cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 1351cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1352cfcd5f6bSMarri Devender Rao return; 1353cfcd5f6bSMarri Devender Rao } 1354cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" 1355cfcd5f6bSMarri Devender Rao << std::to_string(id); 1356cfcd5f6bSMarri Devender Rao std::string certURL = 1357cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1358cfcd5f6bSMarri Devender Rao std::to_string(id); 1359cfcd5f6bSMarri Devender Rao std::string objectPath = certs::authorityObjectPath; 1360cfcd5f6bSMarri Devender Rao objectPath += "/"; 1361cfcd5f6bSMarri Devender Rao objectPath += std::to_string(id); 1362cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 1363cfcd5f6bSMarri Devender Rao certs::authorityServiceName, id, certURL, 1364cfcd5f6bSMarri Devender Rao "TrustStore Certificate"); 1365cfcd5f6bSMarri Devender Rao } 1366cfcd5f6bSMarri Devender Rao }; // TrustStoreCertificate 13675968caeeSMarri Devender Rao } // namespace redfish 1368