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"}}}; 82*30215816SMarri Devender Rao res.jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 83*30215816SMarri Devender Rao {"target", "/redfish/v1/CertificateService/Actions/" 84*30215816SMarri 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 169*30215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 170*30215816SMarri Devender Rao /** 171*30215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 172*30215816SMarri Devender Rao * 173*30215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 174*30215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 175*30215816SMarri Devender Rao * @param[in] service D-Bus service name 176*30215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 177*30215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 178*30215816SMarri Devender Rao * @return None 179*30215816SMarri Devender Rao */ 180*30215816SMarri Devender Rao static void getCSR(const std::shared_ptr<AsyncResp> &asyncResp, 181*30215816SMarri Devender Rao const std::string &certURI, const std::string &service, 182*30215816SMarri Devender Rao const std::string &certObjPath, 183*30215816SMarri Devender Rao const std::string &csrObjPath) 184*30215816SMarri Devender Rao { 185*30215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 186*30215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 187*30215816SMarri Devender Rao << " service=" << service; 188*30215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 189*30215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 190*30215816SMarri Devender Rao const std::string &csr) { 191*30215816SMarri Devender Rao if (ec) 192*30215816SMarri Devender Rao { 193*30215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 194*30215816SMarri Devender Rao messages::internalError(asyncResp->res); 195*30215816SMarri Devender Rao return; 196*30215816SMarri Devender Rao } 197*30215816SMarri Devender Rao if (csr.empty()) 198*30215816SMarri Devender Rao { 199*30215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 200*30215816SMarri Devender Rao messages::internalError(asyncResp->res); 201*30215816SMarri Devender Rao return; 202*30215816SMarri Devender Rao } 203*30215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 204*30215816SMarri Devender Rao asyncResp->res.jsonValue["CertificateCollection"] = { 205*30215816SMarri Devender Rao {"@odata.id", certURI}}; 206*30215816SMarri Devender Rao }, 207*30215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 208*30215816SMarri Devender Rao } 209*30215816SMarri Devender Rao 210*30215816SMarri Devender Rao /** 211*30215816SMarri Devender Rao * Action to Generate CSR 212*30215816SMarri Devender Rao */ 213*30215816SMarri Devender Rao class CertificateActionGenerateCSR : public Node 214*30215816SMarri Devender Rao { 215*30215816SMarri Devender Rao public: 216*30215816SMarri Devender Rao CertificateActionGenerateCSR(CrowApp &app) : 217*30215816SMarri Devender Rao Node(app, "/redfish/v1/CertificateService/Actions/" 218*30215816SMarri Devender Rao "CertificateService.GenerateCSR/") 219*30215816SMarri Devender Rao { 220*30215816SMarri Devender Rao entityPrivileges = { 221*30215816SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 222*30215816SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 223*30215816SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 224*30215816SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 225*30215816SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 226*30215816SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 227*30215816SMarri Devender Rao } 228*30215816SMarri Devender Rao 229*30215816SMarri Devender Rao private: 230*30215816SMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 231*30215816SMarri Devender Rao const std::vector<std::string> ¶ms) override 232*30215816SMarri Devender Rao { 233*30215816SMarri Devender Rao static const int RSA_KEY_BIT_LENGTH = 2048; 234*30215816SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 235*30215816SMarri Devender Rao // Required parameters 236*30215816SMarri Devender Rao std::string city; 237*30215816SMarri Devender Rao std::string commonName; 238*30215816SMarri Devender Rao std::string country; 239*30215816SMarri Devender Rao std::string organization; 240*30215816SMarri Devender Rao std::string organizationalUnit; 241*30215816SMarri Devender Rao std::string state; 242*30215816SMarri Devender Rao nlohmann::json certificateCollection; 243*30215816SMarri Devender Rao 244*30215816SMarri Devender Rao // Optional parameters 245*30215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 246*30215816SMarri Devender Rao std::vector<std::string>(); 247*30215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 248*30215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 249*30215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 250*30215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 251*30215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 252*30215816SMarri Devender Rao std::optional<int64_t> optKeyBitLength = RSA_KEY_BIT_LENGTH; 253*30215816SMarri Devender Rao std::optional<std::string> optKeyCurveId = "prime256v1"; 254*30215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 255*30215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 256*30215816SMarri Devender Rao std::vector<std::string>(); 257*30215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 258*30215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 259*30215816SMarri Devender Rao if (!json_util::readJson( 260*30215816SMarri Devender Rao req, asyncResp->res, "City", city, "CommonName", commonName, 261*30215816SMarri Devender Rao "ContactPerson", optContactPerson, "Country", country, 262*30215816SMarri Devender Rao "Organization", organization, "OrganizationalUnit", 263*30215816SMarri Devender Rao organizationalUnit, "State", state, "CertificateCollection", 264*30215816SMarri Devender Rao certificateCollection, "AlternativeNames", optAlternativeNames, 265*30215816SMarri Devender Rao "ChallengePassword", optChallengePassword, "Email", optEmail, 266*30215816SMarri Devender Rao "GivenName", optGivenName, "Initials", optInitials, 267*30215816SMarri Devender Rao "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, 268*30215816SMarri Devender Rao "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 269*30215816SMarri Devender Rao optKeyUsage, "Surname", optSurname, "UnstructuredName", 270*30215816SMarri Devender Rao optUnstructuredName)) 271*30215816SMarri Devender Rao { 272*30215816SMarri Devender Rao return; 273*30215816SMarri Devender Rao } 274*30215816SMarri Devender Rao 275*30215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 276*30215816SMarri Devender Rao // password, which will likely cause bmcweb to crash on startup if this 277*30215816SMarri Devender Rao // is not set on a post so not allowing the user to set value 278*30215816SMarri Devender Rao if (*optChallengePassword != "") 279*30215816SMarri Devender Rao { 280*30215816SMarri Devender Rao messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 281*30215816SMarri Devender Rao "ChallengePassword"); 282*30215816SMarri Devender Rao return; 283*30215816SMarri Devender Rao } 284*30215816SMarri Devender Rao 285*30215816SMarri Devender Rao std::string certURI; 286*30215816SMarri Devender Rao if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, 287*30215816SMarri Devender Rao "@odata.id", certURI)) 288*30215816SMarri Devender Rao { 289*30215816SMarri Devender Rao return; 290*30215816SMarri Devender Rao } 291*30215816SMarri Devender Rao 292*30215816SMarri Devender Rao std::string objectPath; 293*30215816SMarri Devender Rao std::string service; 294*30215816SMarri Devender Rao if (boost::starts_with( 295*30215816SMarri Devender Rao certURI, 296*30215816SMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 297*30215816SMarri Devender Rao { 298*30215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 299*30215816SMarri Devender Rao service = certs::httpsServiceName; 300*30215816SMarri Devender Rao } 301*30215816SMarri Devender Rao else 302*30215816SMarri Devender Rao { 303*30215816SMarri Devender Rao messages::actionParameterNotSupported( 304*30215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 305*30215816SMarri Devender Rao return; 306*30215816SMarri Devender Rao } 307*30215816SMarri Devender Rao 308*30215816SMarri Devender Rao // supporting only EC and RSA algorithm 309*30215816SMarri Devender Rao if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 310*30215816SMarri Devender Rao { 311*30215816SMarri Devender Rao messages::actionParameterNotSupported( 312*30215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 313*30215816SMarri Devender Rao return; 314*30215816SMarri Devender Rao } 315*30215816SMarri Devender Rao 316*30215816SMarri Devender Rao // supporting only 2048 key bit length for RSA algorithm due to time 317*30215816SMarri Devender Rao // consumed in generating private key 318*30215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 319*30215816SMarri Devender Rao *optKeyBitLength != RSA_KEY_BIT_LENGTH) 320*30215816SMarri Devender Rao { 321*30215816SMarri Devender Rao messages::propertyValueNotInList(asyncResp->res, 322*30215816SMarri Devender Rao std::to_string(*optKeyBitLength), 323*30215816SMarri Devender Rao "KeyBitLength"); 324*30215816SMarri Devender Rao return; 325*30215816SMarri Devender Rao } 326*30215816SMarri Devender Rao 327*30215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 328*30215816SMarri Devender Rao if (boost::starts_with( 329*30215816SMarri Devender Rao certURI, 330*30215816SMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 331*30215816SMarri Devender Rao { 332*30215816SMarri Devender Rao if (optKeyUsage->size() == 0) 333*30215816SMarri Devender Rao { 334*30215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 335*30215816SMarri Devender Rao } 336*30215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 337*30215816SMarri Devender Rao { 338*30215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 339*30215816SMarri Devender Rao { 340*30215816SMarri Devender Rao messages::propertyValueNotInList( 341*30215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 342*30215816SMarri Devender Rao return; 343*30215816SMarri Devender Rao } 344*30215816SMarri Devender Rao } 345*30215816SMarri Devender Rao else 346*30215816SMarri Devender Rao { 347*30215816SMarri Devender Rao messages::actionParameterNotSupported( 348*30215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 349*30215816SMarri Devender Rao return; 350*30215816SMarri Devender Rao } 351*30215816SMarri Devender Rao } 352*30215816SMarri Devender Rao 353*30215816SMarri Devender Rao // Only allow one CSR matcher at a time so setting retry time-out and 354*30215816SMarri Devender Rao // timer expiry to 10 seconds for now. 355*30215816SMarri Devender Rao static const int TIME_OUT = 10; 356*30215816SMarri Devender Rao if (csrMatcher) 357*30215816SMarri Devender Rao { 358*30215816SMarri Devender Rao res.addHeader("Retry-After", std::to_string(TIME_OUT)); 359*30215816SMarri Devender Rao messages::serviceTemporarilyUnavailable(asyncResp->res, 360*30215816SMarri Devender Rao std::to_string(TIME_OUT)); 361*30215816SMarri Devender Rao return; 362*30215816SMarri Devender Rao } 363*30215816SMarri Devender Rao 364*30215816SMarri Devender Rao // Make this static so it survives outside this method 365*30215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 366*30215816SMarri Devender Rao timeout.expires_after(std::chrono::seconds(TIME_OUT)); 367*30215816SMarri Devender Rao timeout.async_wait([asyncResp](const boost::system::error_code &ec) { 368*30215816SMarri Devender Rao csrMatcher = nullptr; 369*30215816SMarri Devender Rao if (ec) 370*30215816SMarri Devender Rao { 371*30215816SMarri Devender Rao // operation_aborted is expected if timer is canceled before 372*30215816SMarri Devender Rao // completion. 373*30215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 374*30215816SMarri Devender Rao { 375*30215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 376*30215816SMarri Devender Rao } 377*30215816SMarri Devender Rao return; 378*30215816SMarri Devender Rao } 379*30215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 380*30215816SMarri Devender Rao messages::internalError(asyncResp->res); 381*30215816SMarri Devender Rao }); 382*30215816SMarri Devender Rao 383*30215816SMarri Devender Rao // create a matcher to wait on CSR object 384*30215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 385*30215816SMarri Devender Rao std::string match("type='signal'," 386*30215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 387*30215816SMarri Devender Rao "path='" + 388*30215816SMarri Devender Rao objectPath + 389*30215816SMarri Devender Rao "'," 390*30215816SMarri Devender Rao "member='InterfacesAdded'"); 391*30215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 392*30215816SMarri Devender Rao *crow::connections::systemBus, match, 393*30215816SMarri Devender Rao [asyncResp, service, objectPath, 394*30215816SMarri Devender Rao certURI](sdbusplus::message::message &m) { 395*30215816SMarri Devender Rao boost::system::error_code ec; 396*30215816SMarri Devender Rao timeout.cancel(ec); 397*30215816SMarri Devender Rao if (ec) 398*30215816SMarri Devender Rao { 399*30215816SMarri Devender Rao BMCWEB_LOG_ERROR << "error canceling timer " << ec; 400*30215816SMarri Devender Rao csrMatcher = nullptr; 401*30215816SMarri Devender Rao } 402*30215816SMarri Devender Rao if (m.is_method_error()) 403*30215816SMarri Devender Rao { 404*30215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 405*30215816SMarri Devender Rao messages::internalError(asyncResp->res); 406*30215816SMarri Devender Rao return; 407*30215816SMarri Devender Rao } 408*30215816SMarri Devender Rao std::vector<std::pair< 409*30215816SMarri Devender Rao std::string, std::vector<std::pair< 410*30215816SMarri Devender Rao std::string, std::variant<std::string>>>>> 411*30215816SMarri Devender Rao interfacesProperties; 412*30215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 413*30215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 414*30215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 415*30215816SMarri Devender Rao for (auto &interface : interfacesProperties) 416*30215816SMarri Devender Rao { 417*30215816SMarri Devender Rao if (interface.first == "xyz.openbmc_project.Certs.CSR") 418*30215816SMarri Devender Rao { 419*30215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 420*30215816SMarri Devender Rao csrObjectPath.str); 421*30215816SMarri Devender Rao break; 422*30215816SMarri Devender Rao } 423*30215816SMarri Devender Rao } 424*30215816SMarri Devender Rao }); 425*30215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 426*30215816SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 427*30215816SMarri Devender Rao const std::string &path) { 428*30215816SMarri Devender Rao if (ec) 429*30215816SMarri Devender Rao { 430*30215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message(); 431*30215816SMarri Devender Rao messages::internalError(asyncResp->res); 432*30215816SMarri Devender Rao return; 433*30215816SMarri Devender Rao } 434*30215816SMarri Devender Rao }, 435*30215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 436*30215816SMarri Devender Rao "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 437*30215816SMarri Devender Rao commonName, *optContactPerson, country, *optEmail, *optGivenName, 438*30215816SMarri Devender Rao *optInitials, *optKeyBitLength, *optKeyCurveId, 439*30215816SMarri Devender Rao *optKeyPairAlgorithm, *optKeyUsage, organization, 440*30215816SMarri Devender Rao organizationalUnit, state, *optSurname, *optUnstructuredName); 441*30215816SMarri Devender Rao } 442*30215816SMarri Devender Rao }; // CertificateActionGenerateCSR 443*30215816SMarri Devender Rao 4445968caeeSMarri Devender Rao /** 4455968caeeSMarri Devender Rao * @brief Parse and update Certficate Issue/Subject property 4465968caeeSMarri Devender Rao * 4475968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4485968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4495968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4505968caeeSMarri Devender Rao * @return None 4515968caeeSMarri Devender Rao */ 4525968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json &out, 4535968caeeSMarri Devender Rao const std::string_view value) 4545968caeeSMarri Devender Rao { 4555968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 4565968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 4575968caeeSMarri Devender Rao while (i != value.end()) 4585968caeeSMarri Devender Rao { 4595968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 4605968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 4615968caeeSMarri Devender Rao { 4625968caeeSMarri Devender Rao i++; 4635968caeeSMarri Devender Rao } 4645968caeeSMarri Devender Rao if (i == value.end()) 4655968caeeSMarri Devender Rao { 4665968caeeSMarri Devender Rao break; 4675968caeeSMarri Devender Rao } 4685968caeeSMarri Devender Rao const std::string_view key(tokenBegin, i - tokenBegin); 4695968caeeSMarri Devender Rao i++; 4705968caeeSMarri Devender Rao tokenBegin = i; 4715968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 4725968caeeSMarri Devender Rao { 4735968caeeSMarri Devender Rao i++; 4745968caeeSMarri Devender Rao } 4755968caeeSMarri Devender Rao const std::string_view val(tokenBegin, i - tokenBegin); 4765968caeeSMarri Devender Rao if (key == "L") 4775968caeeSMarri Devender Rao { 4785968caeeSMarri Devender Rao out["City"] = val; 4795968caeeSMarri Devender Rao } 4805968caeeSMarri Devender Rao else if (key == "CN") 4815968caeeSMarri Devender Rao { 4825968caeeSMarri Devender Rao out["CommonName"] = val; 4835968caeeSMarri Devender Rao } 4845968caeeSMarri Devender Rao else if (key == "C") 4855968caeeSMarri Devender Rao { 4865968caeeSMarri Devender Rao out["Country"] = val; 4875968caeeSMarri Devender Rao } 4885968caeeSMarri Devender Rao else if (key == "O") 4895968caeeSMarri Devender Rao { 4905968caeeSMarri Devender Rao out["Organization"] = val; 4915968caeeSMarri Devender Rao } 4925968caeeSMarri Devender Rao else if (key == "OU") 4935968caeeSMarri Devender Rao { 4945968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 4955968caeeSMarri Devender Rao } 4965968caeeSMarri Devender Rao else if (key == "ST") 4975968caeeSMarri Devender Rao { 4985968caeeSMarri Devender Rao out["State"] = val; 4995968caeeSMarri Devender Rao } 5005968caeeSMarri Devender Rao // skip comma character 5015968caeeSMarri Devender Rao if (i != value.end()) 5025968caeeSMarri Devender Rao { 5035968caeeSMarri Devender Rao i++; 5045968caeeSMarri Devender Rao } 5055968caeeSMarri Devender Rao } 5065968caeeSMarri Devender Rao } 5075968caeeSMarri Devender Rao 5085968caeeSMarri Devender Rao /** 5095968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5105968caeeSMarri Devender Rao * message 5115968caeeSMarri Devender Rao * 5125968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5135968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5145968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5155968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5165968caeeSMarri Devender Rao * @param[in] name name of the certificate 5175968caeeSMarri Devender Rao * @return None 5185968caeeSMarri Devender Rao */ 5195968caeeSMarri Devender Rao static void getCertificateProperties( 5205968caeeSMarri Devender Rao const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath, 52137cce918SMarri Devender Rao const std::string &service, long certId, const std::string &certURL, 52237cce918SMarri Devender Rao const std::string &name) 5235968caeeSMarri Devender Rao { 5245968caeeSMarri Devender Rao using PropertyType = 5255968caeeSMarri Devender Rao std::variant<std::string, uint64_t, std::vector<std::string>>; 5265968caeeSMarri Devender Rao using PropertiesMap = boost::container::flat_map<std::string, PropertyType>; 5275968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5285968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5295968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 53037cce918SMarri Devender Rao [asyncResp, certURL, certId, name](const boost::system::error_code ec, 5315968caeeSMarri Devender Rao const PropertiesMap &properties) { 5325968caeeSMarri Devender Rao if (ec) 5335968caeeSMarri Devender Rao { 5345968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5358aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5368aae75adSMarri Devender Rao std::to_string(certId)); 5375968caeeSMarri Devender Rao return; 5385968caeeSMarri Devender Rao } 5395968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 5405968caeeSMarri Devender Rao {"@odata.id", certURL}, 5415968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 5425968caeeSMarri Devender Rao {"@odata.context", 5435968caeeSMarri Devender Rao "/redfish/v1/$metadata#Certificate.Certificate"}, 5445968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 5455968caeeSMarri Devender Rao {"Name", name}, 5465968caeeSMarri Devender Rao {"Description", name}}; 5475968caeeSMarri Devender Rao for (const auto &property : properties) 5485968caeeSMarri Devender Rao { 5495968caeeSMarri Devender Rao if (property.first == "CertificateString") 5505968caeeSMarri Devender Rao { 5515968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 5525968caeeSMarri Devender Rao const std::string *value = 5535968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 5545968caeeSMarri Devender Rao if (value) 5555968caeeSMarri Devender Rao { 55637cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 5575968caeeSMarri Devender Rao } 5585968caeeSMarri Devender Rao } 5595968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 5605968caeeSMarri Devender Rao { 5615968caeeSMarri Devender Rao nlohmann::json &keyUsage = 5625968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 5635968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 5645968caeeSMarri Devender Rao const std::vector<std::string> *value = 56537cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 5665968caeeSMarri Devender Rao if (value) 5675968caeeSMarri Devender Rao { 5685968caeeSMarri Devender Rao for (const std::string &usage : *value) 5695968caeeSMarri Devender Rao { 5705968caeeSMarri Devender Rao keyUsage.push_back(usage); 5715968caeeSMarri Devender Rao } 5725968caeeSMarri Devender Rao } 5735968caeeSMarri Devender Rao } 5745968caeeSMarri Devender Rao else if (property.first == "Issuer") 5755968caeeSMarri Devender Rao { 5765968caeeSMarri Devender Rao const std::string *value = 5775968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 5785968caeeSMarri Devender Rao if (value) 5795968caeeSMarri Devender Rao { 5805968caeeSMarri Devender Rao updateCertIssuerOrSubject( 5815968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 5825968caeeSMarri Devender Rao } 5835968caeeSMarri Devender Rao } 5845968caeeSMarri Devender Rao else if (property.first == "Subject") 5855968caeeSMarri Devender Rao { 5865968caeeSMarri Devender Rao const std::string *value = 5875968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 5885968caeeSMarri Devender Rao if (value) 5895968caeeSMarri Devender Rao { 5905968caeeSMarri Devender Rao updateCertIssuerOrSubject( 59137cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 5925968caeeSMarri Devender Rao } 5935968caeeSMarri Devender Rao } 5945968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 5955968caeeSMarri Devender Rao { 5965968caeeSMarri Devender Rao const uint64_t *value = 5975968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 5985968caeeSMarri Devender Rao if (value) 5995968caeeSMarri Devender Rao { 60037cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6015968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6025968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6035968caeeSMarri Devender Rao } 6045968caeeSMarri Devender Rao } 6055968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6065968caeeSMarri Devender Rao { 6075968caeeSMarri Devender Rao const uint64_t *value = 6085968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6095968caeeSMarri Devender Rao if (value) 6105968caeeSMarri Devender Rao { 61137cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6125968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6135968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6145968caeeSMarri Devender Rao } 6155968caeeSMarri Devender Rao } 6165968caeeSMarri Devender Rao } 6175968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6185968caeeSMarri Devender Rao }, 6195968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6205968caeeSMarri Devender Rao certs::certPropIntf); 6215968caeeSMarri Devender Rao } 6225968caeeSMarri Devender Rao 6235968caeeSMarri Devender Rao using GetObjectType = 6245968caeeSMarri Devender Rao std::vector<std::pair<std::string, std::vector<std::string>>>; 6255968caeeSMarri Devender Rao 6265968caeeSMarri Devender Rao /** 6275968caeeSMarri Devender Rao * Action to replace an existing certificate 6285968caeeSMarri Devender Rao */ 6295968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node 6305968caeeSMarri Devender Rao { 6315968caeeSMarri Devender Rao public: 6325968caeeSMarri Devender Rao CertificateActionsReplaceCertificate(CrowApp &app) : 6335968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/Actions/" 6345968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate/") 6355968caeeSMarri Devender Rao { 6365968caeeSMarri Devender Rao entityPrivileges = { 6375968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 6385968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 6395968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 6405968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 6415968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 6425968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 6435968caeeSMarri Devender Rao } 6445968caeeSMarri Devender Rao 6455968caeeSMarri Devender Rao private: 6465968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 6475968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 6485968caeeSMarri Devender Rao { 6495968caeeSMarri Devender Rao std::string certificate; 6505968caeeSMarri Devender Rao nlohmann::json certificateUri; 6515968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 6525968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 6535968caeeSMarri Devender Rao if (!json_util::readJson(req, asyncResp->res, "CertificateString", 6545968caeeSMarri Devender Rao certificate, "CertificateUri", certificateUri, 6555968caeeSMarri Devender Rao "CertificateType", certificateType)) 6565968caeeSMarri Devender Rao { 6575968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 6585968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 6595968caeeSMarri Devender Rao return; 6605968caeeSMarri Devender Rao } 6615968caeeSMarri Devender Rao 6625968caeeSMarri Devender Rao if (!certificateType) 6635968caeeSMarri Devender Rao { 6645968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 6655968caeeSMarri Devender Rao return; 6665968caeeSMarri Devender Rao } 6675968caeeSMarri Devender Rao if (certificateType != "PEM") 6685968caeeSMarri Devender Rao { 6695968caeeSMarri Devender Rao messages::actionParameterNotSupported( 6705968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 6715968caeeSMarri Devender Rao return; 6725968caeeSMarri Devender Rao } 6735968caeeSMarri Devender Rao 6745968caeeSMarri Devender Rao std::string certURI; 6755968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 6765968caeeSMarri Devender Rao "@odata.id", certURI)) 6775968caeeSMarri Devender Rao { 6785968caeeSMarri Devender Rao messages::actionParameterMissing( 6795968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 6805968caeeSMarri Devender Rao return; 6815968caeeSMarri Devender Rao } 6825968caeeSMarri Devender Rao 6835968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 6845968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 6855968caeeSMarri Devender Rao if (id < 0) 6865968caeeSMarri Devender Rao { 6875968caeeSMarri Devender Rao messages::actionParameterValueFormatError(asyncResp->res, certURI, 6885968caeeSMarri Devender Rao "CertificateUri", 6895968caeeSMarri Devender Rao "ReplaceCertificate"); 6905968caeeSMarri Devender Rao return; 6915968caeeSMarri Devender Rao } 6925968caeeSMarri Devender Rao std::string objectPath; 6935968caeeSMarri Devender Rao std::string name; 69437cce918SMarri Devender Rao std::string service; 6955968caeeSMarri Devender Rao if (boost::starts_with( 6965968caeeSMarri Devender Rao certURI, 6975968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 6985968caeeSMarri Devender Rao { 6995968caeeSMarri Devender Rao objectPath = 7005968caeeSMarri Devender Rao std::string(certs::httpsObjectPath) + "/" + std::to_string(id); 7015968caeeSMarri Devender Rao name = "HTTPS certificate"; 70237cce918SMarri Devender Rao service = certs::httpsServiceName; 70337cce918SMarri Devender Rao } 70437cce918SMarri Devender Rao else if (boost::starts_with( 70537cce918SMarri Devender Rao certURI, "/redfish/v1/AccountService/LDAP/Certificates/")) 70637cce918SMarri Devender Rao { 70737cce918SMarri Devender Rao objectPath = 70837cce918SMarri Devender Rao std::string(certs::ldapObjectPath) + "/" + std::to_string(id); 70937cce918SMarri Devender Rao name = "LDAP certificate"; 71037cce918SMarri Devender Rao service = certs::ldapServiceName; 7115968caeeSMarri Devender Rao } 7125968caeeSMarri Devender Rao else 7135968caeeSMarri Devender Rao { 7145968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7155968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7165968caeeSMarri Devender Rao return; 7175968caeeSMarri Devender Rao } 7185968caeeSMarri Devender Rao 7195968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7205968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7215968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 72237cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7235968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7245968caeeSMarri Devender Rao if (ec) 7255968caeeSMarri Devender Rao { 7265968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 7278aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7288aae75adSMarri Devender Rao std::to_string(id)); 7295968caeeSMarri Devender Rao return; 7305968caeeSMarri Devender Rao } 73137cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 7325968caeeSMarri Devender Rao certURI, name); 7335968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 7345968caeeSMarri Devender Rao << certFile->getCertFilePath(); 7355968caeeSMarri Devender Rao }, 7365968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 7375968caeeSMarri Devender Rao certFile->getCertFilePath()); 7385968caeeSMarri Devender Rao } 7395968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate 7405968caeeSMarri Devender Rao 7415968caeeSMarri Devender Rao /** 7425968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 7435968caeeSMarri Devender Rao * of a component, account or service. 7445968caeeSMarri Devender Rao */ 7455968caeeSMarri Devender Rao class HTTPSCertificate : public Node 7465968caeeSMarri Devender Rao { 7475968caeeSMarri Devender Rao public: 7485968caeeSMarri Devender Rao template <typename CrowApp> 7495968caeeSMarri Devender Rao HTTPSCertificate(CrowApp &app) : 7505968caeeSMarri Devender Rao Node(app, 7515968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" 7525968caeeSMarri Devender Rao "<str>/", 7535968caeeSMarri Devender Rao std::string()) 7545968caeeSMarri Devender Rao { 7555968caeeSMarri Devender Rao entityPrivileges = { 7565968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 7575968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 7585968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 7595968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 7605968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 7615968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 7625968caeeSMarri Devender Rao } 7635968caeeSMarri Devender Rao 7645968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 7655968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 7665968caeeSMarri Devender Rao { 7675968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 7685968caeeSMarri Devender Rao if (params.size() != 1) 7695968caeeSMarri Devender Rao { 7705968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 7715968caeeSMarri Devender Rao return; 7725968caeeSMarri Devender Rao } 7735968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 7745968caeeSMarri Devender Rao 7755968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id); 7765968caeeSMarri Devender Rao std::string certURL = 7775968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 7785968caeeSMarri Devender Rao std::to_string(id); 7795968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 7805968caeeSMarri Devender Rao objectPath += "/"; 7815968caeeSMarri Devender Rao objectPath += std::to_string(id); 78237cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName, 78337cce918SMarri Devender Rao id, certURL, "HTTPS Certificate"); 7845968caeeSMarri Devender Rao } 7855968caeeSMarri Devender Rao 7865968caeeSMarri Devender Rao }; // namespace redfish 7875968caeeSMarri Devender Rao 7885968caeeSMarri Devender Rao /** 7895968caeeSMarri Devender Rao * Collection of HTTPS certificates 7905968caeeSMarri Devender Rao */ 7915968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node 7925968caeeSMarri Devender Rao { 7935968caeeSMarri Devender Rao public: 7945968caeeSMarri Devender Rao template <typename CrowApp> 7955968caeeSMarri Devender Rao HTTPSCertificateCollection(CrowApp &app) : 7965968caeeSMarri Devender Rao Node(app, 7975968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 7985968caeeSMarri Devender Rao { 7995968caeeSMarri Devender Rao entityPrivileges = { 8005968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 8015968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 8025968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 8035968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 8045968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 8055968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 8065968caeeSMarri Devender Rao } 8075968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 8085968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 8095968caeeSMarri Devender Rao { 8105968caeeSMarri Devender Rao res.jsonValue = { 8115968caeeSMarri Devender Rao {"@odata.id", 8125968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 8135968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 8145968caeeSMarri Devender Rao {"@odata.context", 8155968caeeSMarri Devender Rao "/redfish/v1/" 8165968caeeSMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 8175968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 8185968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 8195968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 8205968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8215968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 8225968caeeSMarri Devender Rao const ManagedObjectType &certs) { 8235968caeeSMarri Devender Rao if (ec) 8245968caeeSMarri Devender Rao { 8255968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8265968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8275968caeeSMarri Devender Rao return; 8285968caeeSMarri Devender Rao } 82937cce918SMarri Devender Rao nlohmann::json &members = asyncResp->res.jsonValue["Members"]; 8305968caeeSMarri Devender Rao members = nlohmann::json::array(); 8315968caeeSMarri Devender Rao for (const auto &cert : certs) 8325968caeeSMarri Devender Rao { 8335968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 83437cce918SMarri Devender Rao if (id >= 0) 8355968caeeSMarri Devender Rao { 8365968caeeSMarri Devender Rao members.push_back( 8375968caeeSMarri Devender Rao {{"@odata.id", 8385968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/" 8395968caeeSMarri Devender Rao "NetworkProtocol/HTTPS/Certificates/" + 8405968caeeSMarri Devender Rao std::to_string(id)}}); 8415968caeeSMarri Devender Rao } 8425968caeeSMarri Devender Rao } 8435968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 8445968caeeSMarri Devender Rao members.size(); 8455968caeeSMarri Devender Rao }, 84637cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 84737cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 8485968caeeSMarri Devender Rao } 8495968caeeSMarri Devender Rao 8505968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 8515968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 8525968caeeSMarri Devender Rao { 8535968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 8545968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 8555968caeeSMarri Devender Rao asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"}, 8565968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 8575968caeeSMarri Devender Rao 8585968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 8595968caeeSMarri Devender Rao std::make_shared<CertificateFile>(req.body); 8605968caeeSMarri Devender Rao 8615968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8625968caeeSMarri Devender Rao [asyncResp, certFile](const boost::system::error_code ec) { 8635968caeeSMarri Devender Rao if (ec) 8645968caeeSMarri Devender Rao { 8655968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8665968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8675968caeeSMarri Devender Rao return; 8685968caeeSMarri Devender Rao } 8695968caeeSMarri Devender Rao // TODO: Issue#84 supporting only 1 certificate 8705968caeeSMarri Devender Rao long certId = 1; 8715968caeeSMarri Devender Rao std::string certURL = 8725968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/" 8735968caeeSMarri Devender Rao "Certificates/" + 8745968caeeSMarri Devender Rao std::to_string(certId); 87537cce918SMarri Devender Rao std::string objectPath = std::string(certs::httpsObjectPath) + 87637cce918SMarri Devender Rao "/" + std::to_string(certId); 87737cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 87837cce918SMarri Devender Rao certs::httpsServiceName, certId, 8795968caeeSMarri Devender Rao certURL, "HTTPS Certificate"); 8805968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 8815968caeeSMarri Devender Rao << certFile->getCertFilePath(); 8825968caeeSMarri Devender Rao }, 88337cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 88437cce918SMarri Devender Rao certs::certInstallIntf, "Install", certFile->getCertFilePath()); 8855968caeeSMarri Devender Rao } 8865968caeeSMarri Devender Rao }; // HTTPSCertificateCollection 8875968caeeSMarri Devender Rao 8885968caeeSMarri Devender Rao /** 8895968caeeSMarri Devender Rao * The certificate location schema defines a resource that an administrator 8905968caeeSMarri Devender Rao * can use in order to locate all certificates installed on a given service. 8915968caeeSMarri Devender Rao */ 8925968caeeSMarri Devender Rao class CertificateLocations : public Node 8935968caeeSMarri Devender Rao { 8945968caeeSMarri Devender Rao public: 8955968caeeSMarri Devender Rao template <typename CrowApp> 8965968caeeSMarri Devender Rao CertificateLocations(CrowApp &app) : 8975968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/CertificateLocations/") 8985968caeeSMarri Devender Rao { 8995968caeeSMarri Devender Rao entityPrivileges = { 9005968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 9015968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 9025968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 9035968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 9045968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 9055968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9065968caeeSMarri Devender Rao } 9075968caeeSMarri Devender Rao 9085968caeeSMarri Devender Rao private: 9095968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 9105968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 9115968caeeSMarri Devender Rao { 9125968caeeSMarri Devender Rao res.jsonValue = { 9135968caeeSMarri Devender Rao {"@odata.id", 9145968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}, 9155968caeeSMarri Devender Rao {"@odata.type", 9165968caeeSMarri Devender Rao "#CertificateLocations.v1_0_0.CertificateLocations"}, 9175968caeeSMarri Devender Rao {"@odata.context", 9185968caeeSMarri Devender Rao "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"}, 9195968caeeSMarri Devender Rao {"Name", "Certificate Locations"}, 9205968caeeSMarri Devender Rao {"Id", "CertificateLocations"}, 9215968caeeSMarri Devender Rao {"Description", 9225968caeeSMarri Devender Rao "Defines a resource that an administrator can use in order to " 9235968caeeSMarri Devender Rao "locate all certificates installed on a given service"}}; 9245968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 9255968caeeSMarri Devender Rao nlohmann::json &links = 9265968caeeSMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 9275968caeeSMarri Devender Rao links = nlohmann::json::array(); 9285968caeeSMarri Devender Rao getCertificateLocations( 9295968caeeSMarri Devender Rao asyncResp, 9305968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 93137cce918SMarri Devender Rao certs::httpsObjectPath, certs::httpsServiceName); 93237cce918SMarri Devender Rao getCertificateLocations(asyncResp, 93337cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/", 93437cce918SMarri Devender Rao certs::ldapObjectPath, certs::ldapServiceName); 93537cce918SMarri Devender Rao } 93637cce918SMarri Devender Rao /** 93737cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 93837cce918SMarri Devender Rao * response 93937cce918SMarri Devender Rao * 94037cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 94137cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 94237cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 94337cce918SMarri Devender Rao * @return None 94437cce918SMarri Devender Rao */ 94537cce918SMarri Devender Rao void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp, 94637cce918SMarri Devender Rao const std::string &certURL, 94737cce918SMarri Devender Rao const std::string &path, 94837cce918SMarri Devender Rao const std::string &service) 94937cce918SMarri Devender Rao { 95037cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 95137cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 95237cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 95337cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 95437cce918SMarri Devender Rao const ManagedObjectType &certs) { 95537cce918SMarri Devender Rao if (ec) 95637cce918SMarri Devender Rao { 95737cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 95837cce918SMarri Devender Rao messages::internalError(asyncResp->res); 95937cce918SMarri Devender Rao return; 96037cce918SMarri Devender Rao } 96137cce918SMarri Devender Rao nlohmann::json &links = 96237cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 96337cce918SMarri Devender Rao for (auto &cert : certs) 96437cce918SMarri Devender Rao { 96537cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 96637cce918SMarri Devender Rao if (id >= 0) 96737cce918SMarri Devender Rao { 96837cce918SMarri Devender Rao links.push_back( 96937cce918SMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 97037cce918SMarri Devender Rao } 97137cce918SMarri Devender Rao } 97237cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 97337cce918SMarri Devender Rao links.size(); 97437cce918SMarri Devender Rao }, 97537cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 9765968caeeSMarri Devender Rao } 9775968caeeSMarri Devender Rao }; // CertificateLocations 97837cce918SMarri Devender Rao 97937cce918SMarri Devender Rao /** 98037cce918SMarri Devender Rao * Collection of LDAP certificates 98137cce918SMarri Devender Rao */ 98237cce918SMarri Devender Rao class LDAPCertificateCollection : public Node 98337cce918SMarri Devender Rao { 98437cce918SMarri Devender Rao public: 98537cce918SMarri Devender Rao template <typename CrowApp> 98637cce918SMarri Devender Rao LDAPCertificateCollection(CrowApp &app) : 98737cce918SMarri Devender Rao Node(app, "/redfish/v1/AccountService/LDAP/Certificates/") 98837cce918SMarri Devender Rao { 98937cce918SMarri Devender Rao entityPrivileges = { 99037cce918SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 99137cce918SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 99237cce918SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 99337cce918SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 99437cce918SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 99537cce918SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 99637cce918SMarri Devender Rao } 99737cce918SMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 99837cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 99937cce918SMarri Devender Rao { 100037cce918SMarri Devender Rao res.jsonValue = { 100137cce918SMarri Devender Rao {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, 100237cce918SMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 100337cce918SMarri Devender Rao {"@odata.context", 100437cce918SMarri Devender Rao "/redfish/v1/" 100537cce918SMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 100637cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 100737cce918SMarri Devender Rao {"Description", "A Collection of LDAP certificate instances"}}; 100837cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 100937cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 101037cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 101137cce918SMarri Devender Rao const ManagedObjectType &certs) { 101237cce918SMarri Devender Rao if (ec) 101337cce918SMarri Devender Rao { 101437cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 101537cce918SMarri Devender Rao messages::internalError(asyncResp->res); 101637cce918SMarri Devender Rao return; 101737cce918SMarri Devender Rao } 101837cce918SMarri Devender Rao nlohmann::json &members = asyncResp->res.jsonValue["Members"]; 101937cce918SMarri Devender Rao members = nlohmann::json::array(); 102037cce918SMarri Devender Rao for (const auto &cert : certs) 102137cce918SMarri Devender Rao { 102237cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 102337cce918SMarri Devender Rao if (id >= 0) 102437cce918SMarri Devender Rao { 102537cce918SMarri Devender Rao members.push_back( 102637cce918SMarri Devender Rao {{"@odata.id", "/redfish/v1/AccountService/" 102737cce918SMarri Devender Rao "LDAP/Certificates/" + 102837cce918SMarri Devender Rao std::to_string(id)}}); 102937cce918SMarri Devender Rao } 103037cce918SMarri Devender Rao } 103137cce918SMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 103237cce918SMarri Devender Rao members.size(); 103337cce918SMarri Devender Rao }, 103437cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 103537cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 103637cce918SMarri Devender Rao } 103737cce918SMarri Devender Rao 103837cce918SMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 103937cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 104037cce918SMarri Devender Rao { 104137cce918SMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 104237cce918SMarri Devender Rao std::make_shared<CertificateFile>(req.body); 104337cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 104437cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 104537cce918SMarri Devender Rao [asyncResp, certFile](const boost::system::error_code ec) { 104637cce918SMarri Devender Rao if (ec) 104737cce918SMarri Devender Rao { 104837cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 104937cce918SMarri Devender Rao messages::internalError(asyncResp->res); 105037cce918SMarri Devender Rao return; 105137cce918SMarri Devender Rao } 105237cce918SMarri Devender Rao //// TODO: Issue#84 supporting only 1 certificate 105337cce918SMarri Devender Rao long certId = 1; 105437cce918SMarri Devender Rao std::string certURL = 105537cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 105637cce918SMarri Devender Rao std::to_string(certId); 105737cce918SMarri Devender Rao std::string objectPath = std::string(certs::ldapObjectPath) + 105837cce918SMarri Devender Rao "/" + std::to_string(certId); 105937cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 106037cce918SMarri Devender Rao certs::ldapServiceName, certId, 106137cce918SMarri Devender Rao certURL, "LDAP Certificate"); 106237cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 106337cce918SMarri Devender Rao << certFile->getCertFilePath(); 106437cce918SMarri Devender Rao }, 106537cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 106637cce918SMarri Devender Rao certs::certInstallIntf, "Install", certFile->getCertFilePath()); 106737cce918SMarri Devender Rao } 106837cce918SMarri Devender Rao }; // LDAPCertificateCollection 106937cce918SMarri Devender Rao 107037cce918SMarri Devender Rao /** 107137cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 107237cce918SMarri Devender Rao * of a component, account or service. 107337cce918SMarri Devender Rao */ 107437cce918SMarri Devender Rao class LDAPCertificate : public Node 107537cce918SMarri Devender Rao { 107637cce918SMarri Devender Rao public: 107737cce918SMarri Devender Rao template <typename CrowApp> 107837cce918SMarri Devender Rao LDAPCertificate(CrowApp &app) : 107937cce918SMarri Devender Rao Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/", 108037cce918SMarri Devender Rao std::string()) 108137cce918SMarri Devender Rao { 108237cce918SMarri Devender Rao entityPrivileges = { 108337cce918SMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 108437cce918SMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 108537cce918SMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 108637cce918SMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 108737cce918SMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 108837cce918SMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 108937cce918SMarri Devender Rao } 109037cce918SMarri Devender Rao 109137cce918SMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 109237cce918SMarri Devender Rao const std::vector<std::string> ¶ms) override 109337cce918SMarri Devender Rao { 109437cce918SMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 109537cce918SMarri Devender Rao long id = getIDFromURL(req.url); 109637cce918SMarri Devender Rao if (id < 0) 109737cce918SMarri Devender Rao { 109837cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 109937cce918SMarri Devender Rao messages::internalError(asyncResp->res); 110037cce918SMarri Devender Rao return; 110137cce918SMarri Devender Rao } 110237cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id); 110337cce918SMarri Devender Rao std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" + 110437cce918SMarri Devender Rao std::to_string(id); 110537cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 110637cce918SMarri Devender Rao objectPath += "/"; 110737cce918SMarri Devender Rao objectPath += std::to_string(id); 110837cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, 110937cce918SMarri Devender Rao id, certURL, "LDAP Certificate"); 111037cce918SMarri Devender Rao } 111137cce918SMarri Devender Rao }; // LDAPCertificate 11125968caeeSMarri Devender Rao } // namespace redfish 1113