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"; 375968caeeSMarri Devender Rao } // namespace certs 385968caeeSMarri Devender Rao 395968caeeSMarri Devender Rao /** 405968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 415968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 425968caeeSMarri Devender Rao * are installed. 435968caeeSMarri Devender Rao */ 445968caeeSMarri Devender Rao class CertificateService : public Node 455968caeeSMarri Devender Rao { 465968caeeSMarri Devender Rao public: 475968caeeSMarri Devender Rao CertificateService(CrowApp &app) : 485968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/") 495968caeeSMarri Devender Rao { 505968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 515968caeeSMarri Devender Rao // sevice at https://www.dmtf.org/standards/redfish 525968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 535968caeeSMarri Devender Rao // publish Privilege details for certificate service 545968caeeSMarri Devender Rao entityPrivileges = { 555968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 565968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 575968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 585968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 595968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 605968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 615968caeeSMarri Devender Rao } 625968caeeSMarri Devender Rao 635968caeeSMarri Devender Rao private: 645968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 655968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 665968caeeSMarri Devender Rao { 675968caeeSMarri Devender Rao res.jsonValue = { 685968caeeSMarri Devender Rao {"@odata.type", "#CertificateService.v1_0_0.CertificateService"}, 695968caeeSMarri Devender Rao {"@odata.id", "/redfish/v1/CertificateService"}, 705968caeeSMarri Devender Rao {"@odata.context", 715968caeeSMarri Devender Rao "/redfish/v1/$metadata#CertificateService.CertificateService"}, 725968caeeSMarri Devender Rao {"Id", "CertificateService"}, 735968caeeSMarri Devender Rao {"Name", "Certificate Service"}, 745968caeeSMarri Devender Rao {"Description", "Actions available to manage certificates"}}; 755968caeeSMarri Devender Rao res.jsonValue["CertificateLocations"] = { 765968caeeSMarri Devender Rao {"@odata.id", 775968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}}; 785968caeeSMarri Devender Rao res.jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { 795968caeeSMarri Devender Rao {"target", "/redfish/v1/CertificateService/Actions/" 805968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate"}, 815968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 8230215816SMarri Devender Rao res.jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 8330215816SMarri Devender Rao {"target", "/redfish/v1/CertificateService/Actions/" 8430215816SMarri Devender Rao "CertificateService.GenerateCSR"}}; 855968caeeSMarri Devender Rao res.end(); 865968caeeSMarri Devender Rao } 875968caeeSMarri Devender Rao }; // CertificateService 8837cce918SMarri Devender Rao 895968caeeSMarri Devender Rao /** 905968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 915968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 925968caeeSMarri Devender Rao * @param[in] path URL 935968caeeSMarri Devender Rao * @return -1 on failure and number on success 945968caeeSMarri Devender Rao */ 955968caeeSMarri Devender Rao long getIDFromURL(const std::string_view url) 965968caeeSMarri Devender Rao { 975968caeeSMarri Devender Rao std::size_t found = url.rfind("/"); 985968caeeSMarri Devender Rao if (found == std::string::npos) 995968caeeSMarri Devender Rao { 1005968caeeSMarri Devender Rao return -1; 1015968caeeSMarri Devender Rao } 1025968caeeSMarri Devender Rao if ((found + 1) < url.length()) 1035968caeeSMarri Devender Rao { 1045968caeeSMarri Devender Rao char *endPtr; 1055968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 1065968caeeSMarri Devender Rao long value = std::strtol(str.data(), &endPtr, 10); 10737cce918SMarri Devender Rao if (endPtr != str.end()) 1085968caeeSMarri Devender Rao { 1095968caeeSMarri Devender Rao return -1; 1105968caeeSMarri Devender Rao } 1115968caeeSMarri Devender Rao return value; 1125968caeeSMarri Devender Rao } 1135968caeeSMarri Devender Rao return -1; 1145968caeeSMarri Devender Rao } 1155968caeeSMarri Devender Rao 1165968caeeSMarri Devender Rao /** 1175968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1185968caeeSMarri Devender Rao */ 1195968caeeSMarri Devender Rao class CertificateFile 1205968caeeSMarri Devender Rao { 1215968caeeSMarri Devender Rao public: 1225968caeeSMarri Devender Rao CertificateFile() = delete; 1235968caeeSMarri Devender Rao CertificateFile(const CertificateFile &) = delete; 1245968caeeSMarri Devender Rao CertificateFile &operator=(const CertificateFile &) = delete; 1255968caeeSMarri Devender Rao CertificateFile(CertificateFile &&) = delete; 1265968caeeSMarri Devender Rao CertificateFile &operator=(CertificateFile &&) = delete; 1275968caeeSMarri Devender Rao CertificateFile(const std::string &certString) 1285968caeeSMarri Devender Rao { 1295968caeeSMarri Devender Rao char dirTemplate[] = "/tmp/Certs.XXXXXX"; 1305968caeeSMarri Devender Rao char *tempDirectory = mkdtemp(dirTemplate); 1315968caeeSMarri Devender Rao if (tempDirectory) 1325968caeeSMarri Devender Rao { 1335968caeeSMarri Devender Rao certDirectory = tempDirectory; 1345968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1355968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1365968caeeSMarri Devender Rao std::ofstream::binary | 1375968caeeSMarri Devender Rao std::ofstream::trunc); 1385968caeeSMarri Devender Rao out << certString; 1395968caeeSMarri Devender Rao out.close(); 1405968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile; 1415968caeeSMarri Devender Rao } 1425968caeeSMarri Devender Rao } 1435968caeeSMarri Devender Rao ~CertificateFile() 1445968caeeSMarri Devender Rao { 1455968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1465968caeeSMarri Devender Rao { 1475968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile; 1485968caeeSMarri Devender Rao try 1495968caeeSMarri Devender Rao { 1505968caeeSMarri Devender Rao std::filesystem::remove_all(certDirectory); 1515968caeeSMarri Devender Rao } 1525968caeeSMarri Devender Rao catch (const std::filesystem::filesystem_error &e) 1535968caeeSMarri Devender Rao { 1545968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1555968caeeSMarri Devender Rao << certDirectory; 1565968caeeSMarri Devender Rao } 1575968caeeSMarri Devender Rao } 1585968caeeSMarri Devender Rao } 1595968caeeSMarri Devender Rao std::string getCertFilePath() 1605968caeeSMarri Devender Rao { 1615968caeeSMarri Devender Rao return certificateFile; 1625968caeeSMarri Devender Rao } 1635968caeeSMarri Devender Rao 1645968caeeSMarri Devender Rao private: 1655968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1665968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1675968caeeSMarri Devender Rao }; 1685968caeeSMarri Devender Rao 16930215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 17030215816SMarri Devender Rao /** 17130215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 17230215816SMarri Devender Rao * 17330215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 17430215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 17530215816SMarri Devender Rao * @param[in] service D-Bus service name 17630215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 17730215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 17830215816SMarri Devender Rao * @return None 17930215816SMarri Devender Rao */ 18030215816SMarri Devender Rao static void getCSR(const std::shared_ptr<AsyncResp> &asyncResp, 18130215816SMarri Devender Rao const std::string &certURI, const std::string &service, 18230215816SMarri Devender Rao const std::string &certObjPath, 18330215816SMarri Devender Rao const std::string &csrObjPath) 18430215816SMarri Devender Rao { 18530215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 18630215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 18730215816SMarri Devender Rao << " service=" << service; 18830215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 18930215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 19030215816SMarri Devender Rao const std::string &csr) { 19130215816SMarri Devender Rao if (ec) 19230215816SMarri Devender Rao { 19330215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 19430215816SMarri Devender Rao messages::internalError(asyncResp->res); 19530215816SMarri Devender Rao return; 19630215816SMarri Devender Rao } 19730215816SMarri Devender Rao if (csr.empty()) 19830215816SMarri Devender Rao { 19930215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 20030215816SMarri Devender Rao messages::internalError(asyncResp->res); 20130215816SMarri Devender Rao return; 20230215816SMarri Devender Rao } 20330215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 20430215816SMarri Devender Rao asyncResp->res.jsonValue["CertificateCollection"] = { 20530215816SMarri Devender Rao {"@odata.id", certURI}}; 20630215816SMarri Devender Rao }, 20730215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 20830215816SMarri Devender Rao } 20930215816SMarri Devender Rao 21030215816SMarri Devender Rao /** 21130215816SMarri Devender Rao * Action to Generate CSR 21230215816SMarri Devender Rao */ 21330215816SMarri Devender Rao class CertificateActionGenerateCSR : public Node 21430215816SMarri Devender Rao { 21530215816SMarri Devender Rao public: 21630215816SMarri Devender Rao CertificateActionGenerateCSR(CrowApp &app) : 21730215816SMarri Devender Rao Node(app, "/redfish/v1/CertificateService/Actions/" 21830215816SMarri Devender Rao "CertificateService.GenerateCSR/") 21930215816SMarri Devender Rao { 22030215816SMarri Devender Rao entityPrivileges = { 22130215816SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 22230215816SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 22330215816SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 22430215816SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 22530215816SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 22630215816SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 22730215816SMarri Devender Rao } 22830215816SMarri Devender Rao 22930215816SMarri Devender Rao private: 23030215816SMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 23130215816SMarri Devender Rao const std::vector<std::string> ¶ms) override 23230215816SMarri Devender Rao { 23330215816SMarri Devender Rao static const int RSA_KEY_BIT_LENGTH = 2048; 23430215816SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 23530215816SMarri Devender Rao // Required parameters 23630215816SMarri Devender Rao std::string city; 23730215816SMarri Devender Rao std::string commonName; 23830215816SMarri Devender Rao std::string country; 23930215816SMarri Devender Rao std::string organization; 24030215816SMarri Devender Rao std::string organizationalUnit; 24130215816SMarri Devender Rao std::string state; 24230215816SMarri Devender Rao nlohmann::json certificateCollection; 24330215816SMarri Devender Rao 24430215816SMarri Devender Rao // Optional parameters 24530215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 24630215816SMarri Devender Rao std::vector<std::string>(); 24730215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 24830215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 24930215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 25030215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 25130215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 25230215816SMarri Devender Rao std::optional<int64_t> optKeyBitLength = RSA_KEY_BIT_LENGTH; 25330215816SMarri Devender Rao std::optional<std::string> optKeyCurveId = "prime256v1"; 25430215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 25530215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 25630215816SMarri Devender Rao std::vector<std::string>(); 25730215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 25830215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 25930215816SMarri Devender Rao if (!json_util::readJson( 26030215816SMarri Devender Rao req, asyncResp->res, "City", city, "CommonName", commonName, 26130215816SMarri Devender Rao "ContactPerson", optContactPerson, "Country", country, 26230215816SMarri Devender Rao "Organization", organization, "OrganizationalUnit", 26330215816SMarri Devender Rao organizationalUnit, "State", state, "CertificateCollection", 26430215816SMarri Devender Rao certificateCollection, "AlternativeNames", optAlternativeNames, 26530215816SMarri Devender Rao "ChallengePassword", optChallengePassword, "Email", optEmail, 26630215816SMarri Devender Rao "GivenName", optGivenName, "Initials", optInitials, 26730215816SMarri Devender Rao "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, 26830215816SMarri Devender Rao "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 26930215816SMarri Devender Rao optKeyUsage, "Surname", optSurname, "UnstructuredName", 27030215816SMarri Devender Rao optUnstructuredName)) 27130215816SMarri Devender Rao { 27230215816SMarri Devender Rao return; 27330215816SMarri Devender Rao } 27430215816SMarri Devender Rao 27530215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 27630215816SMarri Devender Rao // password, which will likely cause bmcweb to crash on startup if this 27730215816SMarri Devender Rao // is not set on a post so not allowing the user to set value 27830215816SMarri Devender Rao if (*optChallengePassword != "") 27930215816SMarri Devender Rao { 28030215816SMarri Devender Rao messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 28130215816SMarri Devender Rao "ChallengePassword"); 28230215816SMarri Devender Rao return; 28330215816SMarri Devender Rao } 28430215816SMarri Devender Rao 28530215816SMarri Devender Rao std::string certURI; 28630215816SMarri Devender Rao if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, 28730215816SMarri Devender Rao "@odata.id", certURI)) 28830215816SMarri Devender Rao { 28930215816SMarri Devender Rao return; 29030215816SMarri Devender Rao } 29130215816SMarri Devender Rao 29230215816SMarri Devender Rao std::string objectPath; 29330215816SMarri Devender Rao std::string service; 29430215816SMarri Devender Rao if (boost::starts_with( 29530215816SMarri Devender Rao certURI, 29630215816SMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 29730215816SMarri Devender Rao { 29830215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 29930215816SMarri Devender Rao service = certs::httpsServiceName; 30030215816SMarri Devender Rao } 301*3b7f0149SMarri Devender Rao else if (boost::starts_with( 302*3b7f0149SMarri Devender Rao certURI, "/redfish/v1/AccountService/LDAP/Certificates")) 303*3b7f0149SMarri Devender Rao { 304*3b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 305*3b7f0149SMarri Devender Rao service = certs::ldapServiceName; 306*3b7f0149SMarri Devender Rao } 30730215816SMarri Devender Rao else 30830215816SMarri Devender Rao { 30930215816SMarri Devender Rao messages::actionParameterNotSupported( 31030215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 31130215816SMarri Devender Rao return; 31230215816SMarri Devender Rao } 31330215816SMarri Devender Rao 31430215816SMarri Devender Rao // supporting only EC and RSA algorithm 31530215816SMarri Devender Rao if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 31630215816SMarri Devender Rao { 31730215816SMarri Devender Rao messages::actionParameterNotSupported( 31830215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 31930215816SMarri Devender Rao return; 32030215816SMarri Devender Rao } 32130215816SMarri Devender Rao 32230215816SMarri Devender Rao // supporting only 2048 key bit length for RSA algorithm due to time 32330215816SMarri Devender Rao // consumed in generating private key 32430215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 32530215816SMarri Devender Rao *optKeyBitLength != RSA_KEY_BIT_LENGTH) 32630215816SMarri Devender Rao { 32730215816SMarri Devender Rao messages::propertyValueNotInList(asyncResp->res, 32830215816SMarri Devender Rao std::to_string(*optKeyBitLength), 32930215816SMarri Devender Rao "KeyBitLength"); 33030215816SMarri Devender Rao return; 33130215816SMarri Devender Rao } 33230215816SMarri Devender Rao 33330215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 33430215816SMarri Devender Rao if (boost::starts_with( 33530215816SMarri Devender Rao certURI, 33630215816SMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 33730215816SMarri Devender Rao { 33830215816SMarri Devender Rao if (optKeyUsage->size() == 0) 33930215816SMarri Devender Rao { 34030215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 34130215816SMarri Devender Rao } 34230215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 34330215816SMarri Devender Rao { 34430215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 34530215816SMarri Devender Rao { 34630215816SMarri Devender Rao messages::propertyValueNotInList( 34730215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 34830215816SMarri Devender Rao return; 34930215816SMarri Devender Rao } 35030215816SMarri Devender Rao } 35130215816SMarri Devender Rao else 35230215816SMarri Devender Rao { 35330215816SMarri Devender Rao messages::actionParameterNotSupported( 35430215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 35530215816SMarri Devender Rao return; 35630215816SMarri Devender Rao } 35730215816SMarri Devender Rao } 358*3b7f0149SMarri Devender Rao else if (boost::starts_with( 359*3b7f0149SMarri Devender Rao certURI, "/redfish/v1/AccountService/LDAP/Certificates")) 360*3b7f0149SMarri Devender Rao { 361*3b7f0149SMarri Devender Rao if (optKeyUsage->size() == 0) 362*3b7f0149SMarri Devender Rao { 363*3b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 364*3b7f0149SMarri Devender Rao } 365*3b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 366*3b7f0149SMarri Devender Rao { 367*3b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 368*3b7f0149SMarri Devender Rao { 369*3b7f0149SMarri Devender Rao messages::propertyValueNotInList( 370*3b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 371*3b7f0149SMarri Devender Rao return; 372*3b7f0149SMarri Devender Rao } 373*3b7f0149SMarri Devender Rao } 374*3b7f0149SMarri Devender Rao else 375*3b7f0149SMarri Devender Rao { 376*3b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 377*3b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 378*3b7f0149SMarri Devender Rao return; 379*3b7f0149SMarri Devender Rao } 380*3b7f0149SMarri Devender Rao } 38130215816SMarri Devender Rao 38230215816SMarri Devender Rao // Only allow one CSR matcher at a time so setting retry time-out and 38330215816SMarri Devender Rao // timer expiry to 10 seconds for now. 38430215816SMarri Devender Rao static const int TIME_OUT = 10; 38530215816SMarri Devender Rao if (csrMatcher) 38630215816SMarri Devender Rao { 38730215816SMarri Devender Rao res.addHeader("Retry-After", std::to_string(TIME_OUT)); 38830215816SMarri Devender Rao messages::serviceTemporarilyUnavailable(asyncResp->res, 38930215816SMarri Devender Rao std::to_string(TIME_OUT)); 39030215816SMarri Devender Rao return; 39130215816SMarri Devender Rao } 39230215816SMarri Devender Rao 39330215816SMarri Devender Rao // Make this static so it survives outside this method 39430215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 39530215816SMarri Devender Rao timeout.expires_after(std::chrono::seconds(TIME_OUT)); 39630215816SMarri Devender Rao timeout.async_wait([asyncResp](const boost::system::error_code &ec) { 39730215816SMarri Devender Rao csrMatcher = nullptr; 39830215816SMarri Devender Rao if (ec) 39930215816SMarri Devender Rao { 40030215816SMarri Devender Rao // operation_aborted is expected if timer is canceled before 40130215816SMarri Devender Rao // completion. 40230215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 40330215816SMarri Devender Rao { 40430215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 40530215816SMarri Devender Rao } 40630215816SMarri Devender Rao return; 40730215816SMarri Devender Rao } 40830215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 40930215816SMarri Devender Rao messages::internalError(asyncResp->res); 41030215816SMarri Devender Rao }); 41130215816SMarri Devender Rao 41230215816SMarri Devender Rao // create a matcher to wait on CSR object 41330215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 41430215816SMarri Devender Rao std::string match("type='signal'," 41530215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 41630215816SMarri Devender Rao "path='" + 41730215816SMarri Devender Rao objectPath + 41830215816SMarri Devender Rao "'," 41930215816SMarri Devender Rao "member='InterfacesAdded'"); 42030215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 42130215816SMarri Devender Rao *crow::connections::systemBus, match, 42230215816SMarri Devender Rao [asyncResp, service, objectPath, 42330215816SMarri Devender Rao certURI](sdbusplus::message::message &m) { 42430215816SMarri Devender Rao boost::system::error_code ec; 42530215816SMarri Devender Rao timeout.cancel(ec); 42630215816SMarri Devender Rao if (ec) 42730215816SMarri Devender Rao { 42830215816SMarri Devender Rao BMCWEB_LOG_ERROR << "error canceling timer " << ec; 42930215816SMarri Devender Rao csrMatcher = nullptr; 43030215816SMarri Devender Rao } 43130215816SMarri Devender Rao if (m.is_method_error()) 43230215816SMarri Devender Rao { 43330215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 43430215816SMarri Devender Rao messages::internalError(asyncResp->res); 43530215816SMarri Devender Rao return; 43630215816SMarri Devender Rao } 43730215816SMarri Devender Rao std::vector<std::pair< 43830215816SMarri Devender Rao std::string, std::vector<std::pair< 43930215816SMarri Devender Rao std::string, std::variant<std::string>>>>> 44030215816SMarri Devender Rao interfacesProperties; 44130215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 44230215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 44330215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 44430215816SMarri Devender Rao for (auto &interface : interfacesProperties) 44530215816SMarri Devender Rao { 44630215816SMarri Devender Rao if (interface.first == "xyz.openbmc_project.Certs.CSR") 44730215816SMarri Devender Rao { 44830215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 44930215816SMarri Devender Rao csrObjectPath.str); 45030215816SMarri Devender Rao break; 45130215816SMarri Devender Rao } 45230215816SMarri Devender Rao } 45330215816SMarri Devender Rao }); 45430215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 45530215816SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 45630215816SMarri Devender Rao const std::string &path) { 45730215816SMarri Devender Rao if (ec) 45830215816SMarri Devender Rao { 45930215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message(); 46030215816SMarri Devender Rao messages::internalError(asyncResp->res); 46130215816SMarri Devender Rao return; 46230215816SMarri Devender Rao } 46330215816SMarri Devender Rao }, 46430215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 46530215816SMarri Devender Rao "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 46630215816SMarri Devender Rao commonName, *optContactPerson, country, *optEmail, *optGivenName, 46730215816SMarri Devender Rao *optInitials, *optKeyBitLength, *optKeyCurveId, 46830215816SMarri Devender Rao *optKeyPairAlgorithm, *optKeyUsage, organization, 46930215816SMarri Devender Rao organizationalUnit, state, *optSurname, *optUnstructuredName); 47030215816SMarri Devender Rao } 47130215816SMarri Devender Rao }; // CertificateActionGenerateCSR 47230215816SMarri Devender Rao 4735968caeeSMarri Devender Rao /** 4745968caeeSMarri Devender Rao * @brief Parse and update Certficate Issue/Subject property 4755968caeeSMarri Devender Rao * 4765968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4775968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4785968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4795968caeeSMarri Devender Rao * @return None 4805968caeeSMarri Devender Rao */ 4815968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json &out, 4825968caeeSMarri Devender Rao const std::string_view value) 4835968caeeSMarri Devender Rao { 4845968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 4855968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 4865968caeeSMarri Devender Rao while (i != value.end()) 4875968caeeSMarri Devender Rao { 4885968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 4895968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 4905968caeeSMarri Devender Rao { 4915968caeeSMarri Devender Rao i++; 4925968caeeSMarri Devender Rao } 4935968caeeSMarri Devender Rao if (i == value.end()) 4945968caeeSMarri Devender Rao { 4955968caeeSMarri Devender Rao break; 4965968caeeSMarri Devender Rao } 4975968caeeSMarri Devender Rao const std::string_view key(tokenBegin, i - tokenBegin); 4985968caeeSMarri Devender Rao i++; 4995968caeeSMarri Devender Rao tokenBegin = i; 5005968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 5015968caeeSMarri Devender Rao { 5025968caeeSMarri Devender Rao i++; 5035968caeeSMarri Devender Rao } 5045968caeeSMarri Devender Rao const std::string_view val(tokenBegin, i - tokenBegin); 5055968caeeSMarri Devender Rao if (key == "L") 5065968caeeSMarri Devender Rao { 5075968caeeSMarri Devender Rao out["City"] = val; 5085968caeeSMarri Devender Rao } 5095968caeeSMarri Devender Rao else if (key == "CN") 5105968caeeSMarri Devender Rao { 5115968caeeSMarri Devender Rao out["CommonName"] = val; 5125968caeeSMarri Devender Rao } 5135968caeeSMarri Devender Rao else if (key == "C") 5145968caeeSMarri Devender Rao { 5155968caeeSMarri Devender Rao out["Country"] = val; 5165968caeeSMarri Devender Rao } 5175968caeeSMarri Devender Rao else if (key == "O") 5185968caeeSMarri Devender Rao { 5195968caeeSMarri Devender Rao out["Organization"] = val; 5205968caeeSMarri Devender Rao } 5215968caeeSMarri Devender Rao else if (key == "OU") 5225968caeeSMarri Devender Rao { 5235968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5245968caeeSMarri Devender Rao } 5255968caeeSMarri Devender Rao else if (key == "ST") 5265968caeeSMarri Devender Rao { 5275968caeeSMarri Devender Rao out["State"] = val; 5285968caeeSMarri Devender Rao } 5295968caeeSMarri Devender Rao // skip comma character 5305968caeeSMarri Devender Rao if (i != value.end()) 5315968caeeSMarri Devender Rao { 5325968caeeSMarri Devender Rao i++; 5335968caeeSMarri Devender Rao } 5345968caeeSMarri Devender Rao } 5355968caeeSMarri Devender Rao } 5365968caeeSMarri Devender Rao 5375968caeeSMarri Devender Rao /** 5385968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5395968caeeSMarri Devender Rao * message 5405968caeeSMarri Devender Rao * 5415968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5425968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5435968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5445968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5455968caeeSMarri Devender Rao * @param[in] name name of the certificate 5465968caeeSMarri Devender Rao * @return None 5475968caeeSMarri Devender Rao */ 5485968caeeSMarri Devender Rao static void getCertificateProperties( 5495968caeeSMarri Devender Rao const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath, 55037cce918SMarri Devender Rao const std::string &service, long certId, const std::string &certURL, 55137cce918SMarri Devender Rao const std::string &name) 5525968caeeSMarri Devender Rao { 5535968caeeSMarri Devender Rao using PropertyType = 5545968caeeSMarri Devender Rao std::variant<std::string, uint64_t, std::vector<std::string>>; 5555968caeeSMarri Devender Rao using PropertiesMap = boost::container::flat_map<std::string, PropertyType>; 5565968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5575968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5585968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 55937cce918SMarri Devender Rao [asyncResp, certURL, certId, name](const boost::system::error_code ec, 5605968caeeSMarri Devender Rao const PropertiesMap &properties) { 5615968caeeSMarri Devender Rao if (ec) 5625968caeeSMarri Devender Rao { 5635968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5648aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5658aae75adSMarri Devender Rao std::to_string(certId)); 5665968caeeSMarri Devender Rao return; 5675968caeeSMarri Devender Rao } 5685968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 5695968caeeSMarri Devender Rao {"@odata.id", certURL}, 5705968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 5715968caeeSMarri Devender Rao {"@odata.context", 5725968caeeSMarri Devender Rao "/redfish/v1/$metadata#Certificate.Certificate"}, 5735968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 5745968caeeSMarri Devender Rao {"Name", name}, 5755968caeeSMarri Devender Rao {"Description", name}}; 5765968caeeSMarri Devender Rao for (const auto &property : properties) 5775968caeeSMarri Devender Rao { 5785968caeeSMarri Devender Rao if (property.first == "CertificateString") 5795968caeeSMarri Devender Rao { 5805968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 5815968caeeSMarri Devender Rao const std::string *value = 5825968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 5835968caeeSMarri Devender Rao if (value) 5845968caeeSMarri Devender Rao { 58537cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 5865968caeeSMarri Devender Rao } 5875968caeeSMarri Devender Rao } 5885968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 5895968caeeSMarri Devender Rao { 5905968caeeSMarri Devender Rao nlohmann::json &keyUsage = 5915968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 5925968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 5935968caeeSMarri Devender Rao const std::vector<std::string> *value = 59437cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 5955968caeeSMarri Devender Rao if (value) 5965968caeeSMarri Devender Rao { 5975968caeeSMarri Devender Rao for (const std::string &usage : *value) 5985968caeeSMarri Devender Rao { 5995968caeeSMarri Devender Rao keyUsage.push_back(usage); 6005968caeeSMarri Devender Rao } 6015968caeeSMarri Devender Rao } 6025968caeeSMarri Devender Rao } 6035968caeeSMarri Devender Rao else if (property.first == "Issuer") 6045968caeeSMarri Devender Rao { 6055968caeeSMarri Devender Rao const std::string *value = 6065968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6075968caeeSMarri Devender Rao if (value) 6085968caeeSMarri Devender Rao { 6095968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6105968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6115968caeeSMarri Devender Rao } 6125968caeeSMarri Devender Rao } 6135968caeeSMarri Devender Rao else if (property.first == "Subject") 6145968caeeSMarri Devender Rao { 6155968caeeSMarri Devender Rao const std::string *value = 6165968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6175968caeeSMarri Devender Rao if (value) 6185968caeeSMarri Devender Rao { 6195968caeeSMarri Devender Rao updateCertIssuerOrSubject( 62037cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6215968caeeSMarri Devender Rao } 6225968caeeSMarri Devender Rao } 6235968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6245968caeeSMarri Devender Rao { 6255968caeeSMarri Devender Rao const uint64_t *value = 6265968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6275968caeeSMarri Devender Rao if (value) 6285968caeeSMarri Devender Rao { 62937cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6305968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6315968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6325968caeeSMarri Devender Rao } 6335968caeeSMarri Devender Rao } 6345968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6355968caeeSMarri Devender Rao { 6365968caeeSMarri Devender Rao const uint64_t *value = 6375968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6385968caeeSMarri Devender Rao if (value) 6395968caeeSMarri Devender Rao { 64037cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6415968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6425968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6435968caeeSMarri Devender Rao } 6445968caeeSMarri Devender Rao } 6455968caeeSMarri Devender Rao } 6465968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6475968caeeSMarri Devender Rao }, 6485968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6495968caeeSMarri Devender Rao certs::certPropIntf); 6505968caeeSMarri Devender Rao } 6515968caeeSMarri Devender Rao 6525968caeeSMarri Devender Rao using GetObjectType = 6535968caeeSMarri Devender Rao std::vector<std::pair<std::string, std::vector<std::string>>>; 6545968caeeSMarri Devender Rao 6555968caeeSMarri Devender Rao /** 6565968caeeSMarri Devender Rao * Action to replace an existing certificate 6575968caeeSMarri Devender Rao */ 6585968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node 6595968caeeSMarri Devender Rao { 6605968caeeSMarri Devender Rao public: 6615968caeeSMarri Devender Rao CertificateActionsReplaceCertificate(CrowApp &app) : 6625968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/Actions/" 6635968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate/") 6645968caeeSMarri Devender Rao { 6655968caeeSMarri Devender Rao entityPrivileges = { 6665968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 6675968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 6685968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 6695968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 6705968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 6715968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 6725968caeeSMarri Devender Rao } 6735968caeeSMarri Devender Rao 6745968caeeSMarri Devender Rao private: 6755968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 6765968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 6775968caeeSMarri Devender Rao { 6785968caeeSMarri Devender Rao std::string certificate; 6795968caeeSMarri Devender Rao nlohmann::json certificateUri; 6805968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 6815968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 6825968caeeSMarri Devender Rao if (!json_util::readJson(req, asyncResp->res, "CertificateString", 6835968caeeSMarri Devender Rao certificate, "CertificateUri", certificateUri, 6845968caeeSMarri Devender Rao "CertificateType", certificateType)) 6855968caeeSMarri Devender Rao { 6865968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 6875968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 6885968caeeSMarri Devender Rao return; 6895968caeeSMarri Devender Rao } 6905968caeeSMarri Devender Rao 6915968caeeSMarri Devender Rao if (!certificateType) 6925968caeeSMarri Devender Rao { 6935968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 6945968caeeSMarri Devender Rao return; 6955968caeeSMarri Devender Rao } 6965968caeeSMarri Devender Rao if (certificateType != "PEM") 6975968caeeSMarri Devender Rao { 6985968caeeSMarri Devender Rao messages::actionParameterNotSupported( 6995968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7005968caeeSMarri Devender Rao return; 7015968caeeSMarri Devender Rao } 7025968caeeSMarri Devender Rao 7035968caeeSMarri Devender Rao std::string certURI; 7045968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7055968caeeSMarri Devender Rao "@odata.id", certURI)) 7065968caeeSMarri Devender Rao { 7075968caeeSMarri Devender Rao messages::actionParameterMissing( 7085968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7095968caeeSMarri Devender Rao return; 7105968caeeSMarri Devender Rao } 7115968caeeSMarri Devender Rao 7125968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7135968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7145968caeeSMarri Devender Rao if (id < 0) 7155968caeeSMarri Devender Rao { 7165968caeeSMarri Devender Rao messages::actionParameterValueFormatError(asyncResp->res, certURI, 7175968caeeSMarri Devender Rao "CertificateUri", 7185968caeeSMarri Devender Rao "ReplaceCertificate"); 7195968caeeSMarri Devender Rao return; 7205968caeeSMarri Devender Rao } 7215968caeeSMarri Devender Rao std::string objectPath; 7225968caeeSMarri Devender Rao std::string name; 72337cce918SMarri Devender Rao std::string service; 7245968caeeSMarri Devender Rao if (boost::starts_with( 7255968caeeSMarri Devender Rao certURI, 7265968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 7275968caeeSMarri Devender Rao { 7285968caeeSMarri Devender Rao objectPath = 7295968caeeSMarri Devender Rao std::string(certs::httpsObjectPath) + "/" + std::to_string(id); 7305968caeeSMarri Devender Rao name = "HTTPS certificate"; 73137cce918SMarri Devender Rao service = certs::httpsServiceName; 73237cce918SMarri Devender Rao } 73337cce918SMarri Devender Rao else if (boost::starts_with( 73437cce918SMarri Devender Rao certURI, "/redfish/v1/AccountService/LDAP/Certificates/")) 73537cce918SMarri Devender Rao { 73637cce918SMarri Devender Rao objectPath = 73737cce918SMarri Devender Rao std::string(certs::ldapObjectPath) + "/" + std::to_string(id); 73837cce918SMarri Devender Rao name = "LDAP certificate"; 73937cce918SMarri Devender Rao service = certs::ldapServiceName; 7405968caeeSMarri Devender Rao } 7415968caeeSMarri Devender Rao else 7425968caeeSMarri Devender Rao { 7435968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7445968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7455968caeeSMarri Devender Rao return; 7465968caeeSMarri Devender Rao } 7475968caeeSMarri Devender Rao 7485968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7495968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7505968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 75137cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7525968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7535968caeeSMarri Devender Rao if (ec) 7545968caeeSMarri Devender Rao { 7555968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 7568aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7578aae75adSMarri Devender Rao std::to_string(id)); 7585968caeeSMarri Devender Rao return; 7595968caeeSMarri Devender Rao } 76037cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 7615968caeeSMarri Devender Rao certURI, name); 7625968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 7635968caeeSMarri Devender Rao << certFile->getCertFilePath(); 7645968caeeSMarri Devender Rao }, 7655968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 7665968caeeSMarri Devender Rao certFile->getCertFilePath()); 7675968caeeSMarri Devender Rao } 7685968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate 7695968caeeSMarri Devender Rao 7705968caeeSMarri Devender Rao /** 7715968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 7725968caeeSMarri Devender Rao * of a component, account or service. 7735968caeeSMarri Devender Rao */ 7745968caeeSMarri Devender Rao class HTTPSCertificate : public Node 7755968caeeSMarri Devender Rao { 7765968caeeSMarri Devender Rao public: 7775968caeeSMarri Devender Rao template <typename CrowApp> 7785968caeeSMarri Devender Rao HTTPSCertificate(CrowApp &app) : 7795968caeeSMarri Devender Rao Node(app, 7805968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" 7815968caeeSMarri Devender Rao "<str>/", 7825968caeeSMarri Devender Rao std::string()) 7835968caeeSMarri Devender Rao { 7845968caeeSMarri Devender Rao entityPrivileges = { 7855968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 7865968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 7875968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 7885968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 7895968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 7905968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 7915968caeeSMarri Devender Rao } 7925968caeeSMarri Devender Rao 7935968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 7945968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 7955968caeeSMarri Devender Rao { 7965968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 7975968caeeSMarri Devender Rao if (params.size() != 1) 7985968caeeSMarri Devender Rao { 7995968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8005968caeeSMarri Devender Rao return; 8015968caeeSMarri Devender Rao } 8025968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8035968caeeSMarri Devender Rao 8045968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id); 8055968caeeSMarri Devender Rao std::string certURL = 8065968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8075968caeeSMarri Devender Rao std::to_string(id); 8085968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8095968caeeSMarri Devender Rao objectPath += "/"; 8105968caeeSMarri Devender Rao objectPath += std::to_string(id); 81137cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName, 81237cce918SMarri Devender Rao id, certURL, "HTTPS Certificate"); 8135968caeeSMarri Devender Rao } 8145968caeeSMarri Devender Rao 8155968caeeSMarri Devender Rao }; // namespace redfish 8165968caeeSMarri Devender Rao 8175968caeeSMarri Devender Rao /** 8185968caeeSMarri Devender Rao * Collection of HTTPS certificates 8195968caeeSMarri Devender Rao */ 8205968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node 8215968caeeSMarri Devender Rao { 8225968caeeSMarri Devender Rao public: 8235968caeeSMarri Devender Rao template <typename CrowApp> 8245968caeeSMarri Devender Rao HTTPSCertificateCollection(CrowApp &app) : 8255968caeeSMarri Devender Rao Node(app, 8265968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 8275968caeeSMarri Devender Rao { 8285968caeeSMarri Devender Rao entityPrivileges = { 8295968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 8305968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 8315968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 8325968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 8335968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 8345968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 8355968caeeSMarri Devender Rao } 8365968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 8375968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 8385968caeeSMarri Devender Rao { 8395968caeeSMarri Devender Rao res.jsonValue = { 8405968caeeSMarri Devender Rao {"@odata.id", 8415968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 8425968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 8435968caeeSMarri Devender Rao {"@odata.context", 8445968caeeSMarri Devender Rao "/redfish/v1/" 8455968caeeSMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 8465968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 8475968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 8485968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 8495968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8505968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 8515968caeeSMarri Devender Rao const ManagedObjectType &certs) { 8525968caeeSMarri Devender Rao if (ec) 8535968caeeSMarri Devender Rao { 8545968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8555968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8565968caeeSMarri Devender Rao return; 8575968caeeSMarri Devender Rao } 85837cce918SMarri Devender Rao nlohmann::json &members = asyncResp->res.jsonValue["Members"]; 8595968caeeSMarri Devender Rao members = nlohmann::json::array(); 8605968caeeSMarri Devender Rao for (const auto &cert : certs) 8615968caeeSMarri Devender Rao { 8625968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 86337cce918SMarri Devender Rao if (id >= 0) 8645968caeeSMarri Devender Rao { 8655968caeeSMarri Devender Rao members.push_back( 8665968caeeSMarri Devender Rao {{"@odata.id", 8675968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/" 8685968caeeSMarri Devender Rao "NetworkProtocol/HTTPS/Certificates/" + 8695968caeeSMarri Devender Rao std::to_string(id)}}); 8705968caeeSMarri Devender Rao } 8715968caeeSMarri Devender Rao } 8725968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 8735968caeeSMarri Devender Rao members.size(); 8745968caeeSMarri Devender Rao }, 87537cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 87637cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 8775968caeeSMarri Devender Rao } 8785968caeeSMarri Devender Rao 8795968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 8805968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 8815968caeeSMarri Devender Rao { 8825968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 8835968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 8845968caeeSMarri Devender Rao asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"}, 8855968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 8865968caeeSMarri Devender Rao 8875968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 8885968caeeSMarri Devender Rao std::make_shared<CertificateFile>(req.body); 8895968caeeSMarri Devender Rao 8905968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8915968caeeSMarri Devender Rao [asyncResp, certFile](const boost::system::error_code ec) { 8925968caeeSMarri Devender Rao if (ec) 8935968caeeSMarri Devender Rao { 8945968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8955968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8965968caeeSMarri Devender Rao return; 8975968caeeSMarri Devender Rao } 8985968caeeSMarri Devender Rao // TODO: Issue#84 supporting only 1 certificate 8995968caeeSMarri Devender Rao long certId = 1; 9005968caeeSMarri Devender Rao std::string certURL = 9015968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/" 9025968caeeSMarri Devender Rao "Certificates/" + 9035968caeeSMarri Devender Rao std::to_string(certId); 90437cce918SMarri Devender Rao std::string objectPath = std::string(certs::httpsObjectPath) + 90537cce918SMarri Devender Rao "/" + std::to_string(certId); 90637cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 90737cce918SMarri Devender Rao certs::httpsServiceName, certId, 9085968caeeSMarri Devender Rao certURL, "HTTPS Certificate"); 9095968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9105968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9115968caeeSMarri Devender Rao }, 91237cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 91337cce918SMarri Devender Rao certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9145968caeeSMarri Devender Rao } 9155968caeeSMarri Devender Rao }; // HTTPSCertificateCollection 9165968caeeSMarri Devender Rao 9175968caeeSMarri Devender Rao /** 9185968caeeSMarri Devender Rao * The certificate location schema defines a resource that an administrator 9195968caeeSMarri Devender Rao * can use in order to locate all certificates installed on a given service. 9205968caeeSMarri Devender Rao */ 9215968caeeSMarri Devender Rao class CertificateLocations : public Node 9225968caeeSMarri Devender Rao { 9235968caeeSMarri Devender Rao public: 9245968caeeSMarri Devender Rao template <typename CrowApp> 9255968caeeSMarri Devender Rao CertificateLocations(CrowApp &app) : 9265968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/CertificateLocations/") 9275968caeeSMarri Devender Rao { 9285968caeeSMarri Devender Rao entityPrivileges = { 9295968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 9305968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 9315968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 9325968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 9335968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 9345968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9355968caeeSMarri Devender Rao } 9365968caeeSMarri Devender Rao 9375968caeeSMarri Devender Rao private: 9385968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 9395968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 9405968caeeSMarri Devender Rao { 9415968caeeSMarri Devender Rao res.jsonValue = { 9425968caeeSMarri Devender Rao {"@odata.id", 9435968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}, 9445968caeeSMarri Devender Rao {"@odata.type", 9455968caeeSMarri Devender Rao "#CertificateLocations.v1_0_0.CertificateLocations"}, 9465968caeeSMarri Devender Rao {"@odata.context", 9475968caeeSMarri Devender Rao "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"}, 9485968caeeSMarri Devender Rao {"Name", "Certificate Locations"}, 9495968caeeSMarri Devender Rao {"Id", "CertificateLocations"}, 9505968caeeSMarri Devender Rao {"Description", 9515968caeeSMarri Devender Rao "Defines a resource that an administrator can use in order to " 9525968caeeSMarri Devender Rao "locate all certificates installed on a given service"}}; 9535968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 9545968caeeSMarri Devender Rao nlohmann::json &links = 9555968caeeSMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 9565968caeeSMarri Devender Rao links = nlohmann::json::array(); 9575968caeeSMarri Devender Rao getCertificateLocations( 9585968caeeSMarri Devender Rao asyncResp, 9595968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 96037cce918SMarri Devender Rao certs::httpsObjectPath, certs::httpsServiceName); 96137cce918SMarri Devender Rao getCertificateLocations(asyncResp, 96237cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/", 96337cce918SMarri Devender Rao certs::ldapObjectPath, certs::ldapServiceName); 96437cce918SMarri Devender Rao } 96537cce918SMarri Devender Rao /** 96637cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 96737cce918SMarri Devender Rao * response 96837cce918SMarri Devender Rao * 96937cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 97037cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 97137cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 97237cce918SMarri Devender Rao * @return None 97337cce918SMarri Devender Rao */ 97437cce918SMarri Devender Rao void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp, 97537cce918SMarri Devender Rao const std::string &certURL, 97637cce918SMarri Devender Rao const std::string &path, 97737cce918SMarri Devender Rao const std::string &service) 97837cce918SMarri Devender Rao { 97937cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 98037cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 98137cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 98237cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 98337cce918SMarri Devender Rao const ManagedObjectType &certs) { 98437cce918SMarri Devender Rao if (ec) 98537cce918SMarri Devender Rao { 98637cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 98737cce918SMarri Devender Rao messages::internalError(asyncResp->res); 98837cce918SMarri Devender Rao return; 98937cce918SMarri Devender Rao } 99037cce918SMarri Devender Rao nlohmann::json &links = 99137cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 99237cce918SMarri Devender Rao for (auto &cert : certs) 99337cce918SMarri Devender Rao { 99437cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 99537cce918SMarri Devender Rao if (id >= 0) 99637cce918SMarri Devender Rao { 99737cce918SMarri Devender Rao links.push_back( 99837cce918SMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 99937cce918SMarri Devender Rao } 100037cce918SMarri Devender Rao } 100137cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 100237cce918SMarri Devender Rao links.size(); 100337cce918SMarri Devender Rao }, 100437cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 10055968caeeSMarri Devender Rao } 10065968caeeSMarri Devender Rao }; // CertificateLocations 100737cce918SMarri Devender Rao 100837cce918SMarri Devender Rao /** 100937cce918SMarri Devender Rao * Collection of LDAP certificates 101037cce918SMarri Devender Rao */ 101137cce918SMarri Devender Rao class LDAPCertificateCollection : public Node 101237cce918SMarri Devender Rao { 101337cce918SMarri Devender Rao public: 101437cce918SMarri Devender Rao template <typename CrowApp> 101537cce918SMarri Devender Rao LDAPCertificateCollection(CrowApp &app) : 101637cce918SMarri Devender Rao Node(app, "/redfish/v1/AccountService/LDAP/Certificates/") 101737cce918SMarri Devender Rao { 101837cce918SMarri Devender Rao entityPrivileges = { 101937cce918SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 102037cce918SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 102137cce918SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 102237cce918SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 102337cce918SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 102437cce918SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 102537cce918SMarri Devender Rao } 102637cce918SMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 102737cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 102837cce918SMarri Devender Rao { 102937cce918SMarri Devender Rao res.jsonValue = { 103037cce918SMarri Devender Rao {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, 103137cce918SMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 103237cce918SMarri Devender Rao {"@odata.context", 103337cce918SMarri Devender Rao "/redfish/v1/" 103437cce918SMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 103537cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 103637cce918SMarri Devender Rao {"Description", "A Collection of LDAP certificate instances"}}; 103737cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 103837cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 103937cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 104037cce918SMarri Devender Rao const ManagedObjectType &certs) { 104137cce918SMarri Devender Rao if (ec) 104237cce918SMarri Devender Rao { 104337cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 104437cce918SMarri Devender Rao messages::internalError(asyncResp->res); 104537cce918SMarri Devender Rao return; 104637cce918SMarri Devender Rao } 104737cce918SMarri Devender Rao nlohmann::json &members = asyncResp->res.jsonValue["Members"]; 104837cce918SMarri Devender Rao members = nlohmann::json::array(); 104937cce918SMarri Devender Rao for (const auto &cert : certs) 105037cce918SMarri Devender Rao { 105137cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 105237cce918SMarri Devender Rao if (id >= 0) 105337cce918SMarri Devender Rao { 105437cce918SMarri Devender Rao members.push_back( 105537cce918SMarri Devender Rao {{"@odata.id", "/redfish/v1/AccountService/" 105637cce918SMarri Devender Rao "LDAP/Certificates/" + 105737cce918SMarri Devender Rao std::to_string(id)}}); 105837cce918SMarri Devender Rao } 105937cce918SMarri Devender Rao } 106037cce918SMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 106137cce918SMarri Devender Rao members.size(); 106237cce918SMarri Devender Rao }, 106337cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 106437cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 106537cce918SMarri Devender Rao } 106637cce918SMarri Devender Rao 106737cce918SMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 106837cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 106937cce918SMarri Devender Rao { 107037cce918SMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 107137cce918SMarri Devender Rao std::make_shared<CertificateFile>(req.body); 107237cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 107337cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 107437cce918SMarri Devender Rao [asyncResp, certFile](const boost::system::error_code ec) { 107537cce918SMarri Devender Rao if (ec) 107637cce918SMarri Devender Rao { 107737cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 107837cce918SMarri Devender Rao messages::internalError(asyncResp->res); 107937cce918SMarri Devender Rao return; 108037cce918SMarri Devender Rao } 108137cce918SMarri Devender Rao //// TODO: Issue#84 supporting only 1 certificate 108237cce918SMarri Devender Rao long certId = 1; 108337cce918SMarri Devender Rao std::string certURL = 108437cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 108537cce918SMarri Devender Rao std::to_string(certId); 108637cce918SMarri Devender Rao std::string objectPath = std::string(certs::ldapObjectPath) + 108737cce918SMarri Devender Rao "/" + std::to_string(certId); 108837cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 108937cce918SMarri Devender Rao certs::ldapServiceName, certId, 109037cce918SMarri Devender Rao certURL, "LDAP Certificate"); 109137cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 109237cce918SMarri Devender Rao << certFile->getCertFilePath(); 109337cce918SMarri Devender Rao }, 109437cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 109537cce918SMarri Devender Rao certs::certInstallIntf, "Install", certFile->getCertFilePath()); 109637cce918SMarri Devender Rao } 109737cce918SMarri Devender Rao }; // LDAPCertificateCollection 109837cce918SMarri Devender Rao 109937cce918SMarri Devender Rao /** 110037cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 110137cce918SMarri Devender Rao * of a component, account or service. 110237cce918SMarri Devender Rao */ 110337cce918SMarri Devender Rao class LDAPCertificate : public Node 110437cce918SMarri Devender Rao { 110537cce918SMarri Devender Rao public: 110637cce918SMarri Devender Rao template <typename CrowApp> 110737cce918SMarri Devender Rao LDAPCertificate(CrowApp &app) : 110837cce918SMarri Devender Rao Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/", 110937cce918SMarri Devender Rao std::string()) 111037cce918SMarri Devender Rao { 111137cce918SMarri Devender Rao entityPrivileges = { 111237cce918SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 111337cce918SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 111437cce918SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 111537cce918SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 111637cce918SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 111737cce918SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 111837cce918SMarri Devender Rao } 111937cce918SMarri Devender Rao 112037cce918SMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 112137cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 112237cce918SMarri Devender Rao { 112337cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 112437cce918SMarri Devender Rao long id = getIDFromURL(req.url); 112537cce918SMarri Devender Rao if (id < 0) 112637cce918SMarri Devender Rao { 112737cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 112837cce918SMarri Devender Rao messages::internalError(asyncResp->res); 112937cce918SMarri Devender Rao return; 113037cce918SMarri Devender Rao } 113137cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id); 113237cce918SMarri Devender Rao std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" + 113337cce918SMarri Devender Rao std::to_string(id); 113437cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 113537cce918SMarri Devender Rao objectPath += "/"; 113637cce918SMarri Devender Rao objectPath += std::to_string(id); 113737cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, 113837cce918SMarri Devender Rao id, certURL, "LDAP Certificate"); 113937cce918SMarri Devender Rao } 114037cce918SMarri Devender Rao }; // LDAPCertificate 11415968caeeSMarri Devender Rao } // namespace redfish 1142