1*5968caeeSMarri Devender Rao /* 2*5968caeeSMarri Devender Rao // Copyright (c) 2018 IBM Corporation 3*5968caeeSMarri Devender Rao // 4*5968caeeSMarri Devender Rao // Licensed under the Apache License, Version 2.0 (the "License"); 5*5968caeeSMarri Devender Rao // you may not use this file except in compliance with the License. 6*5968caeeSMarri Devender Rao // You may obtain a copy of the License at 7*5968caeeSMarri Devender Rao // 8*5968caeeSMarri Devender Rao // http://www.apache.org/licenses/LICENSE-2.0 9*5968caeeSMarri Devender Rao // 10*5968caeeSMarri Devender Rao // Unless required by applicable law or agreed to in writing, software 11*5968caeeSMarri Devender Rao // distributed under the License is distributed on an "AS IS" BASIS, 12*5968caeeSMarri Devender Rao // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*5968caeeSMarri Devender Rao // See the License for the specific language governing permissions and 14*5968caeeSMarri Devender Rao // limitations under the License. 15*5968caeeSMarri Devender Rao */ 16*5968caeeSMarri Devender Rao #pragma once 17*5968caeeSMarri Devender Rao 18*5968caeeSMarri Devender Rao #include "node.hpp" 19*5968caeeSMarri Devender Rao 20*5968caeeSMarri Devender Rao #include <variant> 21*5968caeeSMarri Devender Rao namespace redfish 22*5968caeeSMarri Devender Rao { 23*5968caeeSMarri Devender Rao namespace certs 24*5968caeeSMarri Devender Rao { 25*5968caeeSMarri Devender Rao constexpr char const *httpsObjectPath = 26*5968caeeSMarri Devender Rao "/xyz/openbmc_project/certs/server/https"; 27*5968caeeSMarri Devender Rao constexpr char const *certInstallIntf = "xyz.openbmc_project.Certs.Install"; 28*5968caeeSMarri Devender Rao constexpr char const *certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 29*5968caeeSMarri Devender Rao constexpr char const *certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 30*5968caeeSMarri Devender Rao constexpr char const *dbusPropIntf = "org.freedesktop.DBus.Properties"; 31*5968caeeSMarri Devender Rao constexpr char const *dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 32*5968caeeSMarri Devender Rao constexpr char const *mapperBusName = "xyz.openbmc_project.ObjectMapper"; 33*5968caeeSMarri Devender Rao constexpr char const *mapperObjectPath = "/xyz/openbmc_project/object_mapper"; 34*5968caeeSMarri Devender Rao constexpr char const *mapperIntf = "xyz.openbmc_project.ObjectMapper"; 35*5968caeeSMarri Devender Rao } // namespace certs 36*5968caeeSMarri Devender Rao 37*5968caeeSMarri Devender Rao /** 38*5968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 39*5968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 40*5968caeeSMarri Devender Rao * are installed. 41*5968caeeSMarri Devender Rao */ 42*5968caeeSMarri Devender Rao class CertificateService : public Node 43*5968caeeSMarri Devender Rao { 44*5968caeeSMarri Devender Rao public: 45*5968caeeSMarri Devender Rao CertificateService(CrowApp &app) : 46*5968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/") 47*5968caeeSMarri Devender Rao { 48*5968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 49*5968caeeSMarri Devender Rao // sevice at https://www.dmtf.org/standards/redfish 50*5968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 51*5968caeeSMarri Devender Rao // publish Privilege details for certificate service 52*5968caeeSMarri Devender Rao entityPrivileges = { 53*5968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 54*5968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 55*5968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 56*5968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 57*5968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 58*5968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 59*5968caeeSMarri Devender Rao } 60*5968caeeSMarri Devender Rao 61*5968caeeSMarri Devender Rao private: 62*5968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 63*5968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 64*5968caeeSMarri Devender Rao { 65*5968caeeSMarri Devender Rao res.jsonValue = { 66*5968caeeSMarri Devender Rao {"@odata.type", "#CertificateService.v1_0_0.CertificateService"}, 67*5968caeeSMarri Devender Rao {"@odata.id", "/redfish/v1/CertificateService"}, 68*5968caeeSMarri Devender Rao {"@odata.context", 69*5968caeeSMarri Devender Rao "/redfish/v1/$metadata#CertificateService.CertificateService"}, 70*5968caeeSMarri Devender Rao {"Id", "CertificateService"}, 71*5968caeeSMarri Devender Rao {"Name", "Certificate Service"}, 72*5968caeeSMarri Devender Rao {"Description", "Actions available to manage certificates"}}; 73*5968caeeSMarri Devender Rao res.jsonValue["CertificateLocations"] = { 74*5968caeeSMarri Devender Rao {"@odata.id", 75*5968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}}; 76*5968caeeSMarri Devender Rao res.jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { 77*5968caeeSMarri Devender Rao {"target", "/redfish/v1/CertificateService/Actions/" 78*5968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate"}, 79*5968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 80*5968caeeSMarri Devender Rao res.end(); 81*5968caeeSMarri Devender Rao } 82*5968caeeSMarri Devender Rao }; // CertificateService 83*5968caeeSMarri Devender Rao /** 84*5968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 85*5968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 86*5968caeeSMarri Devender Rao * @param[in] path URL 87*5968caeeSMarri Devender Rao * @return -1 on failure and number on success 88*5968caeeSMarri Devender Rao */ 89*5968caeeSMarri Devender Rao long getIDFromURL(const std::string_view url) 90*5968caeeSMarri Devender Rao { 91*5968caeeSMarri Devender Rao std::size_t found = url.rfind("/"); 92*5968caeeSMarri Devender Rao if (found == std::string::npos) 93*5968caeeSMarri Devender Rao { 94*5968caeeSMarri Devender Rao return -1; 95*5968caeeSMarri Devender Rao } 96*5968caeeSMarri Devender Rao if ((found + 1) < url.length()) 97*5968caeeSMarri Devender Rao { 98*5968caeeSMarri Devender Rao char *endPtr; 99*5968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 100*5968caeeSMarri Devender Rao long value = std::strtol(str.data(), &endPtr, 10); 101*5968caeeSMarri Devender Rao if (endPtr != &str.back()) 102*5968caeeSMarri Devender Rao { 103*5968caeeSMarri Devender Rao return -1; 104*5968caeeSMarri Devender Rao } 105*5968caeeSMarri Devender Rao return value; 106*5968caeeSMarri Devender Rao } 107*5968caeeSMarri Devender Rao return -1; 108*5968caeeSMarri Devender Rao } 109*5968caeeSMarri Devender Rao 110*5968caeeSMarri Devender Rao /** 111*5968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 112*5968caeeSMarri Devender Rao */ 113*5968caeeSMarri Devender Rao class CertificateFile 114*5968caeeSMarri Devender Rao { 115*5968caeeSMarri Devender Rao public: 116*5968caeeSMarri Devender Rao CertificateFile() = delete; 117*5968caeeSMarri Devender Rao CertificateFile(const CertificateFile &) = delete; 118*5968caeeSMarri Devender Rao CertificateFile &operator=(const CertificateFile &) = delete; 119*5968caeeSMarri Devender Rao CertificateFile(CertificateFile &&) = delete; 120*5968caeeSMarri Devender Rao CertificateFile &operator=(CertificateFile &&) = delete; 121*5968caeeSMarri Devender Rao CertificateFile(const std::string &certString) 122*5968caeeSMarri Devender Rao { 123*5968caeeSMarri Devender Rao char dirTemplate[] = "/tmp/Certs.XXXXXX"; 124*5968caeeSMarri Devender Rao char *tempDirectory = mkdtemp(dirTemplate); 125*5968caeeSMarri Devender Rao if (tempDirectory) 126*5968caeeSMarri Devender Rao { 127*5968caeeSMarri Devender Rao certDirectory = tempDirectory; 128*5968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 129*5968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 130*5968caeeSMarri Devender Rao std::ofstream::binary | 131*5968caeeSMarri Devender Rao std::ofstream::trunc); 132*5968caeeSMarri Devender Rao out << certString; 133*5968caeeSMarri Devender Rao out.close(); 134*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile; 135*5968caeeSMarri Devender Rao } 136*5968caeeSMarri Devender Rao } 137*5968caeeSMarri Devender Rao ~CertificateFile() 138*5968caeeSMarri Devender Rao { 139*5968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 140*5968caeeSMarri Devender Rao { 141*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile; 142*5968caeeSMarri Devender Rao try 143*5968caeeSMarri Devender Rao { 144*5968caeeSMarri Devender Rao std::filesystem::remove_all(certDirectory); 145*5968caeeSMarri Devender Rao } 146*5968caeeSMarri Devender Rao catch (const std::filesystem::filesystem_error &e) 147*5968caeeSMarri Devender Rao { 148*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 149*5968caeeSMarri Devender Rao << certDirectory; 150*5968caeeSMarri Devender Rao } 151*5968caeeSMarri Devender Rao } 152*5968caeeSMarri Devender Rao } 153*5968caeeSMarri Devender Rao std::string getCertFilePath() 154*5968caeeSMarri Devender Rao { 155*5968caeeSMarri Devender Rao return certificateFile; 156*5968caeeSMarri Devender Rao } 157*5968caeeSMarri Devender Rao 158*5968caeeSMarri Devender Rao private: 159*5968caeeSMarri Devender Rao std::filesystem::path certificateFile; 160*5968caeeSMarri Devender Rao std::filesystem::path certDirectory; 161*5968caeeSMarri Devender Rao }; 162*5968caeeSMarri Devender Rao 163*5968caeeSMarri Devender Rao /** 164*5968caeeSMarri Devender Rao * @brief Parse and update Certficate Issue/Subject property 165*5968caeeSMarri Devender Rao * 166*5968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 167*5968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 168*5968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 169*5968caeeSMarri Devender Rao * @return None 170*5968caeeSMarri Devender Rao */ 171*5968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json &out, 172*5968caeeSMarri Devender Rao const std::string_view value) 173*5968caeeSMarri Devender Rao { 174*5968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 175*5968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 176*5968caeeSMarri Devender Rao while (i != value.end()) 177*5968caeeSMarri Devender Rao { 178*5968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 179*5968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 180*5968caeeSMarri Devender Rao { 181*5968caeeSMarri Devender Rao i++; 182*5968caeeSMarri Devender Rao } 183*5968caeeSMarri Devender Rao if (i == value.end()) 184*5968caeeSMarri Devender Rao { 185*5968caeeSMarri Devender Rao break; 186*5968caeeSMarri Devender Rao } 187*5968caeeSMarri Devender Rao const std::string_view key(tokenBegin, i - tokenBegin); 188*5968caeeSMarri Devender Rao i++; 189*5968caeeSMarri Devender Rao tokenBegin = i; 190*5968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 191*5968caeeSMarri Devender Rao { 192*5968caeeSMarri Devender Rao i++; 193*5968caeeSMarri Devender Rao } 194*5968caeeSMarri Devender Rao const std::string_view val(tokenBegin, i - tokenBegin); 195*5968caeeSMarri Devender Rao if (key == "L") 196*5968caeeSMarri Devender Rao { 197*5968caeeSMarri Devender Rao out["City"] = val; 198*5968caeeSMarri Devender Rao } 199*5968caeeSMarri Devender Rao else if (key == "CN") 200*5968caeeSMarri Devender Rao { 201*5968caeeSMarri Devender Rao out["CommonName"] = val; 202*5968caeeSMarri Devender Rao } 203*5968caeeSMarri Devender Rao else if (key == "C") 204*5968caeeSMarri Devender Rao { 205*5968caeeSMarri Devender Rao out["Country"] = val; 206*5968caeeSMarri Devender Rao } 207*5968caeeSMarri Devender Rao else if (key == "O") 208*5968caeeSMarri Devender Rao { 209*5968caeeSMarri Devender Rao out["Organization"] = val; 210*5968caeeSMarri Devender Rao } 211*5968caeeSMarri Devender Rao else if (key == "OU") 212*5968caeeSMarri Devender Rao { 213*5968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 214*5968caeeSMarri Devender Rao } 215*5968caeeSMarri Devender Rao else if (key == "ST") 216*5968caeeSMarri Devender Rao { 217*5968caeeSMarri Devender Rao out["State"] = val; 218*5968caeeSMarri Devender Rao } 219*5968caeeSMarri Devender Rao // skip comma character 220*5968caeeSMarri Devender Rao if (i != value.end()) 221*5968caeeSMarri Devender Rao { 222*5968caeeSMarri Devender Rao i++; 223*5968caeeSMarri Devender Rao } 224*5968caeeSMarri Devender Rao } 225*5968caeeSMarri Devender Rao } 226*5968caeeSMarri Devender Rao 227*5968caeeSMarri Devender Rao /** 228*5968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 229*5968caeeSMarri Devender Rao * message 230*5968caeeSMarri Devender Rao * 231*5968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 232*5968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 233*5968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 234*5968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 235*5968caeeSMarri Devender Rao * @param[in] name name of the certificate 236*5968caeeSMarri Devender Rao * @return None 237*5968caeeSMarri Devender Rao */ 238*5968caeeSMarri Devender Rao static void getCertificateProperties( 239*5968caeeSMarri Devender Rao const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath, 240*5968caeeSMarri Devender Rao long certId, const std::string &certURL, const std::string &name) 241*5968caeeSMarri Devender Rao { 242*5968caeeSMarri Devender Rao using PropertyType = 243*5968caeeSMarri Devender Rao std::variant<std::string, uint64_t, std::vector<std::string>>; 244*5968caeeSMarri Devender Rao using PropertiesMap = boost::container::flat_map<std::string, PropertyType>; 245*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 246*5968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 247*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 248*5968caeeSMarri Devender Rao [asyncResp, objectPath, certURL, certId, 249*5968caeeSMarri Devender Rao name](const boost::system::error_code ec, const GetObjectType &resp) { 250*5968caeeSMarri Devender Rao if (ec) 251*5968caeeSMarri Devender Rao { 252*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 253*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 254*5968caeeSMarri Devender Rao return; 255*5968caeeSMarri Devender Rao } 256*5968caeeSMarri Devender Rao if (resp.size() > 1 || resp.empty()) 257*5968caeeSMarri Devender Rao { 258*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid number of objects found " 259*5968caeeSMarri Devender Rao << resp.size(); 260*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 261*5968caeeSMarri Devender Rao return; 262*5968caeeSMarri Devender Rao } 263*5968caeeSMarri Devender Rao const std::string &service = resp.begin()->first; 264*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 265*5968caeeSMarri Devender Rao [asyncResp, certURL, certId, 266*5968caeeSMarri Devender Rao name](const boost::system::error_code ec, 267*5968caeeSMarri Devender Rao const PropertiesMap &properties) { 268*5968caeeSMarri Devender Rao if (ec) 269*5968caeeSMarri Devender Rao { 270*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 271*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 272*5968caeeSMarri Devender Rao return; 273*5968caeeSMarri Devender Rao } 274*5968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 275*5968caeeSMarri Devender Rao {"@odata.id", certURL}, 276*5968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 277*5968caeeSMarri Devender Rao {"@odata.context", 278*5968caeeSMarri Devender Rao "/redfish/v1/$metadata#Certificate.Certificate"}, 279*5968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 280*5968caeeSMarri Devender Rao {"Name", name}, 281*5968caeeSMarri Devender Rao {"Description", name}}; 282*5968caeeSMarri Devender Rao for (const auto &property : properties) 283*5968caeeSMarri Devender Rao { 284*5968caeeSMarri Devender Rao if (property.first == "CertificateString") 285*5968caeeSMarri Devender Rao { 286*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 287*5968caeeSMarri Devender Rao const std::string *value = 288*5968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 289*5968caeeSMarri Devender Rao if (value) 290*5968caeeSMarri Devender Rao { 291*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = 292*5968caeeSMarri Devender Rao *value; 293*5968caeeSMarri Devender Rao } 294*5968caeeSMarri Devender Rao } 295*5968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 296*5968caeeSMarri Devender Rao { 297*5968caeeSMarri Devender Rao nlohmann::json &keyUsage = 298*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 299*5968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 300*5968caeeSMarri Devender Rao const std::vector<std::string> *value = 301*5968caeeSMarri Devender Rao std::get_if<std::vector<std::string>>( 302*5968caeeSMarri Devender Rao &property.second); 303*5968caeeSMarri Devender Rao if (value) 304*5968caeeSMarri Devender Rao { 305*5968caeeSMarri Devender Rao for (const std::string &usage : *value) 306*5968caeeSMarri Devender Rao { 307*5968caeeSMarri Devender Rao keyUsage.push_back(usage); 308*5968caeeSMarri Devender Rao } 309*5968caeeSMarri Devender Rao } 310*5968caeeSMarri Devender Rao } 311*5968caeeSMarri Devender Rao else if (property.first == "Issuer") 312*5968caeeSMarri Devender Rao { 313*5968caeeSMarri Devender Rao const std::string *value = 314*5968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 315*5968caeeSMarri Devender Rao if (value) 316*5968caeeSMarri Devender Rao { 317*5968caeeSMarri Devender Rao updateCertIssuerOrSubject( 318*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 319*5968caeeSMarri Devender Rao } 320*5968caeeSMarri Devender Rao } 321*5968caeeSMarri Devender Rao else if (property.first == "Subject") 322*5968caeeSMarri Devender Rao { 323*5968caeeSMarri Devender Rao const std::string *value = 324*5968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 325*5968caeeSMarri Devender Rao if (value) 326*5968caeeSMarri Devender Rao { 327*5968caeeSMarri Devender Rao updateCertIssuerOrSubject( 328*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["Subject"], 329*5968caeeSMarri Devender Rao *value); 330*5968caeeSMarri Devender Rao } 331*5968caeeSMarri Devender Rao } 332*5968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 333*5968caeeSMarri Devender Rao { 334*5968caeeSMarri Devender Rao const uint64_t *value = 335*5968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 336*5968caeeSMarri Devender Rao if (value) 337*5968caeeSMarri Devender Rao { 338*5968caeeSMarri Devender Rao std::time_t time = 339*5968caeeSMarri Devender Rao static_cast<std::time_t>(*value); 340*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 341*5968caeeSMarri Devender Rao crow::utility::getDateTime(time); 342*5968caeeSMarri Devender Rao } 343*5968caeeSMarri Devender Rao } 344*5968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 345*5968caeeSMarri Devender Rao { 346*5968caeeSMarri Devender Rao const uint64_t *value = 347*5968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 348*5968caeeSMarri Devender Rao if (value) 349*5968caeeSMarri Devender Rao { 350*5968caeeSMarri Devender Rao std::time_t time = 351*5968caeeSMarri Devender Rao static_cast<std::time_t>(*value); 352*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 353*5968caeeSMarri Devender Rao crow::utility::getDateTime(time); 354*5968caeeSMarri Devender Rao } 355*5968caeeSMarri Devender Rao } 356*5968caeeSMarri Devender Rao } 357*5968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 358*5968caeeSMarri Devender Rao }, 359*5968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 360*5968caeeSMarri Devender Rao certs::certPropIntf); 361*5968caeeSMarri Devender Rao }, 362*5968caeeSMarri Devender Rao certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, 363*5968caeeSMarri Devender Rao "GetObject", objectPath, 364*5968caeeSMarri Devender Rao std::array<const char *, 1>{certs::certPropIntf}); 365*5968caeeSMarri Devender Rao } 366*5968caeeSMarri Devender Rao 367*5968caeeSMarri Devender Rao using GetObjectType = 368*5968caeeSMarri Devender Rao std::vector<std::pair<std::string, std::vector<std::string>>>; 369*5968caeeSMarri Devender Rao 370*5968caeeSMarri Devender Rao /** 371*5968caeeSMarri Devender Rao * Action to replace an existing certificate 372*5968caeeSMarri Devender Rao */ 373*5968caeeSMarri Devender Rao class CertificateActionsReplaceCertificate : public Node 374*5968caeeSMarri Devender Rao { 375*5968caeeSMarri Devender Rao public: 376*5968caeeSMarri Devender Rao CertificateActionsReplaceCertificate(CrowApp &app) : 377*5968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/Actions/" 378*5968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate/") 379*5968caeeSMarri Devender Rao { 380*5968caeeSMarri Devender Rao entityPrivileges = { 381*5968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 382*5968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 383*5968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 384*5968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 385*5968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 386*5968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 387*5968caeeSMarri Devender Rao } 388*5968caeeSMarri Devender Rao 389*5968caeeSMarri Devender Rao private: 390*5968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 391*5968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 392*5968caeeSMarri Devender Rao { 393*5968caeeSMarri Devender Rao std::string certificate; 394*5968caeeSMarri Devender Rao nlohmann::json certificateUri; 395*5968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 396*5968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 397*5968caeeSMarri Devender Rao if (!json_util::readJson(req, asyncResp->res, "CertificateString", 398*5968caeeSMarri Devender Rao certificate, "CertificateUri", certificateUri, 399*5968caeeSMarri Devender Rao "CertificateType", certificateType)) 400*5968caeeSMarri Devender Rao { 401*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 402*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 403*5968caeeSMarri Devender Rao return; 404*5968caeeSMarri Devender Rao } 405*5968caeeSMarri Devender Rao 406*5968caeeSMarri Devender Rao if (!certificateType) 407*5968caeeSMarri Devender Rao { 408*5968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 409*5968caeeSMarri Devender Rao return; 410*5968caeeSMarri Devender Rao } 411*5968caeeSMarri Devender Rao if (certificateType != "PEM") 412*5968caeeSMarri Devender Rao { 413*5968caeeSMarri Devender Rao messages::actionParameterNotSupported( 414*5968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 415*5968caeeSMarri Devender Rao return; 416*5968caeeSMarri Devender Rao } 417*5968caeeSMarri Devender Rao 418*5968caeeSMarri Devender Rao std::string certURI; 419*5968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 420*5968caeeSMarri Devender Rao "@odata.id", certURI)) 421*5968caeeSMarri Devender Rao { 422*5968caeeSMarri Devender Rao messages::actionParameterMissing( 423*5968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 424*5968caeeSMarri Devender Rao return; 425*5968caeeSMarri Devender Rao } 426*5968caeeSMarri Devender Rao 427*5968caeeSMarri Devender Rao if (!boost::starts_with( 428*5968caeeSMarri Devender Rao certURI, 429*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 430*5968caeeSMarri Devender Rao { 431*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Unsupported certificate URI" << certURI; 432*5968caeeSMarri Devender Rao messages::actionParameterValueFormatError(asyncResp->res, certURI, 433*5968caeeSMarri Devender Rao "CertificateUri", 434*5968caeeSMarri Devender Rao "ReplaceCertificate"); 435*5968caeeSMarri Devender Rao return; 436*5968caeeSMarri Devender Rao } 437*5968caeeSMarri Devender Rao 438*5968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 439*5968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 440*5968caeeSMarri Devender Rao if (id < 0) 441*5968caeeSMarri Devender Rao { 442*5968caeeSMarri Devender Rao messages::actionParameterValueFormatError(asyncResp->res, certURI, 443*5968caeeSMarri Devender Rao "CertificateUri", 444*5968caeeSMarri Devender Rao "ReplaceCertificate"); 445*5968caeeSMarri Devender Rao return; 446*5968caeeSMarri Devender Rao } 447*5968caeeSMarri Devender Rao std::string objectPath; 448*5968caeeSMarri Devender Rao std::string name; 449*5968caeeSMarri Devender Rao if (boost::starts_with( 450*5968caeeSMarri Devender Rao certURI, 451*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 452*5968caeeSMarri Devender Rao { 453*5968caeeSMarri Devender Rao objectPath = 454*5968caeeSMarri Devender Rao std::string(certs::httpsObjectPath) + "/" + std::to_string(id); 455*5968caeeSMarri Devender Rao name = "HTTPS certificate"; 456*5968caeeSMarri Devender Rao } 457*5968caeeSMarri Devender Rao else 458*5968caeeSMarri Devender Rao { 459*5968caeeSMarri Devender Rao messages::actionParameterNotSupported( 460*5968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 461*5968caeeSMarri Devender Rao return; 462*5968caeeSMarri Devender Rao } 463*5968caeeSMarri Devender Rao 464*5968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 465*5968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 466*5968caeeSMarri Devender Rao 467*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 468*5968caeeSMarri Devender Rao [asyncResp, objectPath, certFile, id, certURI, name]( 469*5968caeeSMarri Devender Rao const boost::system::error_code ec, const GetObjectType &resp) { 470*5968caeeSMarri Devender Rao if (ec) 471*5968caeeSMarri Devender Rao { 472*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 473*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 474*5968caeeSMarri Devender Rao return; 475*5968caeeSMarri Devender Rao } 476*5968caeeSMarri Devender Rao if (resp.size() > 1 || resp.empty()) 477*5968caeeSMarri Devender Rao { 478*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid number of objects found " 479*5968caeeSMarri Devender Rao << resp.size(); 480*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 481*5968caeeSMarri Devender Rao return; 482*5968caeeSMarri Devender Rao } 483*5968caeeSMarri Devender Rao const std::string &service = resp.begin()->first; 484*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 485*5968caeeSMarri Devender Rao [asyncResp, certFile, objectPath, certURI, id, 486*5968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 487*5968caeeSMarri Devender Rao if (ec) 488*5968caeeSMarri Devender Rao { 489*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 490*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 491*5968caeeSMarri Devender Rao return; 492*5968caeeSMarri Devender Rao } 493*5968caeeSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, id, 494*5968caeeSMarri Devender Rao certURI, name); 495*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 496*5968caeeSMarri Devender Rao << certFile->getCertFilePath(); 497*5968caeeSMarri Devender Rao }, 498*5968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 499*5968caeeSMarri Devender Rao certFile->getCertFilePath()); 500*5968caeeSMarri Devender Rao }, 501*5968caeeSMarri Devender Rao certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, 502*5968caeeSMarri Devender Rao "GetObject", objectPath, 503*5968caeeSMarri Devender Rao std::array<std::string, 1>({certs::certReplaceIntf})); 504*5968caeeSMarri Devender Rao } 505*5968caeeSMarri Devender Rao }; // CertificateActionsReplaceCertificate 506*5968caeeSMarri Devender Rao 507*5968caeeSMarri Devender Rao /** 508*5968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 509*5968caeeSMarri Devender Rao * of a component, account or service. 510*5968caeeSMarri Devender Rao */ 511*5968caeeSMarri Devender Rao class HTTPSCertificate : public Node 512*5968caeeSMarri Devender Rao { 513*5968caeeSMarri Devender Rao public: 514*5968caeeSMarri Devender Rao template <typename CrowApp> 515*5968caeeSMarri Devender Rao HTTPSCertificate(CrowApp &app) : 516*5968caeeSMarri Devender Rao Node(app, 517*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" 518*5968caeeSMarri Devender Rao "<str>/", 519*5968caeeSMarri Devender Rao std::string()) 520*5968caeeSMarri Devender Rao { 521*5968caeeSMarri Devender Rao entityPrivileges = { 522*5968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 523*5968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 524*5968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 525*5968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 526*5968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 527*5968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 528*5968caeeSMarri Devender Rao } 529*5968caeeSMarri Devender Rao 530*5968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 531*5968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 532*5968caeeSMarri Devender Rao { 533*5968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 534*5968caeeSMarri Devender Rao if (params.size() != 1) 535*5968caeeSMarri Devender Rao { 536*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 537*5968caeeSMarri Devender Rao return; 538*5968caeeSMarri Devender Rao } 539*5968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 540*5968caeeSMarri Devender Rao 541*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" << std::to_string(id); 542*5968caeeSMarri Devender Rao std::string certURL = 543*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 544*5968caeeSMarri Devender Rao std::to_string(id); 545*5968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 546*5968caeeSMarri Devender Rao objectPath += "/"; 547*5968caeeSMarri Devender Rao objectPath += std::to_string(id); 548*5968caeeSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, id, certURL, 549*5968caeeSMarri Devender Rao "HTTPS Certificate"); 550*5968caeeSMarri Devender Rao } 551*5968caeeSMarri Devender Rao 552*5968caeeSMarri Devender Rao }; // namespace redfish 553*5968caeeSMarri Devender Rao 554*5968caeeSMarri Devender Rao /** 555*5968caeeSMarri Devender Rao * Collection of HTTPS certificates 556*5968caeeSMarri Devender Rao */ 557*5968caeeSMarri Devender Rao class HTTPSCertificateCollection : public Node 558*5968caeeSMarri Devender Rao { 559*5968caeeSMarri Devender Rao public: 560*5968caeeSMarri Devender Rao template <typename CrowApp> 561*5968caeeSMarri Devender Rao HTTPSCertificateCollection(CrowApp &app) : 562*5968caeeSMarri Devender Rao Node(app, 563*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 564*5968caeeSMarri Devender Rao { 565*5968caeeSMarri Devender Rao entityPrivileges = { 566*5968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 567*5968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 568*5968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 569*5968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 570*5968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 571*5968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 572*5968caeeSMarri Devender Rao } 573*5968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 574*5968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 575*5968caeeSMarri Devender Rao { 576*5968caeeSMarri Devender Rao res.jsonValue = { 577*5968caeeSMarri Devender Rao {"@odata.id", 578*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 579*5968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 580*5968caeeSMarri Devender Rao {"@odata.context", 581*5968caeeSMarri Devender Rao "/redfish/v1/" 582*5968caeeSMarri Devender Rao "$metadata#CertificateCollection.CertificateCollection"}, 583*5968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 584*5968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 585*5968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 586*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 587*5968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 588*5968caeeSMarri Devender Rao const GetObjectType &resp) { 589*5968caeeSMarri Devender Rao if (ec) 590*5968caeeSMarri Devender Rao { 591*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 592*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 593*5968caeeSMarri Devender Rao return; 594*5968caeeSMarri Devender Rao } 595*5968caeeSMarri Devender Rao if (resp.size() > 1 || resp.empty()) 596*5968caeeSMarri Devender Rao { 597*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid number of objects found " 598*5968caeeSMarri Devender Rao << resp.size(); 599*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 600*5968caeeSMarri Devender Rao return; 601*5968caeeSMarri Devender Rao } 602*5968caeeSMarri Devender Rao const std::string &service = resp.begin()->first; 603*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 604*5968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 605*5968caeeSMarri Devender Rao const ManagedObjectType &certs) { 606*5968caeeSMarri Devender Rao if (ec) 607*5968caeeSMarri Devender Rao { 608*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 609*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 610*5968caeeSMarri Devender Rao return; 611*5968caeeSMarri Devender Rao } 612*5968caeeSMarri Devender Rao nlohmann::json &members = 613*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members"]; 614*5968caeeSMarri Devender Rao members = nlohmann::json::array(); 615*5968caeeSMarri Devender Rao for (const auto &cert : certs) 616*5968caeeSMarri Devender Rao { 617*5968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 618*5968caeeSMarri Devender Rao if (id != -1) 619*5968caeeSMarri Devender Rao { 620*5968caeeSMarri Devender Rao members.push_back( 621*5968caeeSMarri Devender Rao {{"@odata.id", 622*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/" 623*5968caeeSMarri Devender Rao "NetworkProtocol/HTTPS/Certificates/" + 624*5968caeeSMarri Devender Rao std::to_string(id)}}); 625*5968caeeSMarri Devender Rao } 626*5968caeeSMarri Devender Rao } 627*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 628*5968caeeSMarri Devender Rao members.size(); 629*5968caeeSMarri Devender Rao }, 630*5968caeeSMarri Devender Rao service, certs::httpsObjectPath, certs::dbusObjManagerIntf, 631*5968caeeSMarri Devender Rao "GetManagedObjects"); 632*5968caeeSMarri Devender Rao }, 633*5968caeeSMarri Devender Rao certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, 634*5968caeeSMarri Devender Rao "GetObject", certs::httpsObjectPath, 635*5968caeeSMarri Devender Rao std::array<const char *, 1>{certs::certInstallIntf}); 636*5968caeeSMarri Devender Rao } 637*5968caeeSMarri Devender Rao 638*5968caeeSMarri Devender Rao void doPost(crow::Response &res, const crow::Request &req, 639*5968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 640*5968caeeSMarri Devender Rao { 641*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 642*5968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 643*5968caeeSMarri Devender Rao asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"}, 644*5968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 645*5968caeeSMarri Devender Rao 646*5968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 647*5968caeeSMarri Devender Rao std::make_shared<CertificateFile>(req.body); 648*5968caeeSMarri Devender Rao 649*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 650*5968caeeSMarri Devender Rao [asyncResp, certFile](const boost::system::error_code ec, 651*5968caeeSMarri Devender Rao const GetObjectType &resp) { 652*5968caeeSMarri Devender Rao if (ec) 653*5968caeeSMarri Devender Rao { 654*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 655*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 656*5968caeeSMarri Devender Rao return; 657*5968caeeSMarri Devender Rao } 658*5968caeeSMarri Devender Rao if (resp.size() > 1 || resp.empty()) 659*5968caeeSMarri Devender Rao { 660*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid number of objects found " 661*5968caeeSMarri Devender Rao << resp.size(); 662*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 663*5968caeeSMarri Devender Rao return; 664*5968caeeSMarri Devender Rao } 665*5968caeeSMarri Devender Rao const std::string &service = resp.begin()->first; 666*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 667*5968caeeSMarri Devender Rao [asyncResp, certFile](const boost::system::error_code ec) { 668*5968caeeSMarri Devender Rao if (ec) 669*5968caeeSMarri Devender Rao { 670*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 671*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 672*5968caeeSMarri Devender Rao return; 673*5968caeeSMarri Devender Rao } 674*5968caeeSMarri Devender Rao // TODO: Issue#84 supporting only 1 certificate 675*5968caeeSMarri Devender Rao long certId = 1; 676*5968caeeSMarri Devender Rao std::string certURL = 677*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/" 678*5968caeeSMarri Devender Rao "Certificates/" + 679*5968caeeSMarri Devender Rao std::to_string(certId); 680*5968caeeSMarri Devender Rao std::string objectPath = 681*5968caeeSMarri Devender Rao std::string(certs::httpsObjectPath) + "/" + 682*5968caeeSMarri Devender Rao std::to_string(certId); 683*5968caeeSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, certId, 684*5968caeeSMarri Devender Rao certURL, "HTTPS Certificate"); 685*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 686*5968caeeSMarri Devender Rao << certFile->getCertFilePath(); 687*5968caeeSMarri Devender Rao }, 688*5968caeeSMarri Devender Rao service, certs::httpsObjectPath, certs::certInstallIntf, 689*5968caeeSMarri Devender Rao "Install", certFile->getCertFilePath()); 690*5968caeeSMarri Devender Rao }, 691*5968caeeSMarri Devender Rao certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, 692*5968caeeSMarri Devender Rao "GetObject", certs::httpsObjectPath, 693*5968caeeSMarri Devender Rao std::array<const char *, 1>{certs::certInstallIntf}); 694*5968caeeSMarri Devender Rao } 695*5968caeeSMarri Devender Rao }; // HTTPSCertificateCollection 696*5968caeeSMarri Devender Rao 697*5968caeeSMarri Devender Rao /** 698*5968caeeSMarri Devender Rao * @brief Retrieve the certificates installed list and append to the response 699*5968caeeSMarri Devender Rao * 700*5968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 701*5968caeeSMarri Devender Rao * @param[in] certURL Path of the certificate object 702*5968caeeSMarri Devender Rao * @param[in] path Path of the D-Bus service object 703*5968caeeSMarri Devender Rao * @return None 704*5968caeeSMarri Devender Rao */ 705*5968caeeSMarri Devender Rao static void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp, 706*5968caeeSMarri Devender Rao const std::string &certURL, 707*5968caeeSMarri Devender Rao const std::string &path) 708*5968caeeSMarri Devender Rao { 709*5968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 710*5968caeeSMarri Devender Rao << " Path=" << path; 711*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 712*5968caeeSMarri Devender Rao [asyncResp, path, certURL](const boost::system::error_code ec, 713*5968caeeSMarri Devender Rao const GetObjectType &resp) { 714*5968caeeSMarri Devender Rao if (ec) 715*5968caeeSMarri Devender Rao { 716*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 717*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 718*5968caeeSMarri Devender Rao return; 719*5968caeeSMarri Devender Rao } 720*5968caeeSMarri Devender Rao if (resp.size() > 1 || resp.empty()) 721*5968caeeSMarri Devender Rao { 722*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid number of objects found " 723*5968caeeSMarri Devender Rao << resp.size(); 724*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 725*5968caeeSMarri Devender Rao return; 726*5968caeeSMarri Devender Rao } 727*5968caeeSMarri Devender Rao const std::string &service = resp.begin()->first; 728*5968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 729*5968caeeSMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 730*5968caeeSMarri Devender Rao const ManagedObjectType &certs) { 731*5968caeeSMarri Devender Rao if (ec) 732*5968caeeSMarri Devender Rao { 733*5968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 734*5968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 735*5968caeeSMarri Devender Rao return; 736*5968caeeSMarri Devender Rao } 737*5968caeeSMarri Devender Rao nlohmann::json &links = 738*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 739*5968caeeSMarri Devender Rao for (auto &cert : certs) 740*5968caeeSMarri Devender Rao { 741*5968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 742*5968caeeSMarri Devender Rao if (id != -1) 743*5968caeeSMarri Devender Rao { 744*5968caeeSMarri Devender Rao links.push_back( 745*5968caeeSMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 746*5968caeeSMarri Devender Rao } 747*5968caeeSMarri Devender Rao } 748*5968caeeSMarri Devender Rao asyncResp->res 749*5968caeeSMarri Devender Rao .jsonValue["Links"]["Certificates@odata.count"] = 750*5968caeeSMarri Devender Rao links.size(); 751*5968caeeSMarri Devender Rao }, 752*5968caeeSMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 753*5968caeeSMarri Devender Rao }, 754*5968caeeSMarri Devender Rao certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, 755*5968caeeSMarri Devender Rao "GetObject", path, std::array<std::string, 0>()); 756*5968caeeSMarri Devender Rao } 757*5968caeeSMarri Devender Rao 758*5968caeeSMarri Devender Rao /** 759*5968caeeSMarri Devender Rao * The certificate location schema defines a resource that an administrator 760*5968caeeSMarri Devender Rao * can use in order to locate all certificates installed on a given service. 761*5968caeeSMarri Devender Rao */ 762*5968caeeSMarri Devender Rao class CertificateLocations : public Node 763*5968caeeSMarri Devender Rao { 764*5968caeeSMarri Devender Rao public: 765*5968caeeSMarri Devender Rao template <typename CrowApp> 766*5968caeeSMarri Devender Rao CertificateLocations(CrowApp &app) : 767*5968caeeSMarri Devender Rao Node(app, "/redfish/v1/CertificateService/CertificateLocations/") 768*5968caeeSMarri Devender Rao { 769*5968caeeSMarri Devender Rao entityPrivileges = { 770*5968caeeSMarri Devender Rao {boost::beast::http::verb::get, {{"Login"}}}, 771*5968caeeSMarri Devender Rao {boost::beast::http::verb::head, {{"Login"}}}, 772*5968caeeSMarri Devender Rao {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 773*5968caeeSMarri Devender Rao {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 774*5968caeeSMarri Devender Rao {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 775*5968caeeSMarri Devender Rao {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 776*5968caeeSMarri Devender Rao } 777*5968caeeSMarri Devender Rao 778*5968caeeSMarri Devender Rao private: 779*5968caeeSMarri Devender Rao void doGet(crow::Response &res, const crow::Request &req, 780*5968caeeSMarri Devender Rao const std::vector<std::string> ¶ms) override 781*5968caeeSMarri Devender Rao { 782*5968caeeSMarri Devender Rao res.jsonValue = { 783*5968caeeSMarri Devender Rao {"@odata.id", 784*5968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}, 785*5968caeeSMarri Devender Rao {"@odata.type", 786*5968caeeSMarri Devender Rao "#CertificateLocations.v1_0_0.CertificateLocations"}, 787*5968caeeSMarri Devender Rao {"@odata.context", 788*5968caeeSMarri Devender Rao "/redfish/v1/$metadata#CertificateLocations.CertificateLocations"}, 789*5968caeeSMarri Devender Rao {"Name", "Certificate Locations"}, 790*5968caeeSMarri Devender Rao {"Id", "CertificateLocations"}, 791*5968caeeSMarri Devender Rao {"Description", 792*5968caeeSMarri Devender Rao "Defines a resource that an administrator can use in order to " 793*5968caeeSMarri Devender Rao "locate all certificates installed on a given service"}}; 794*5968caeeSMarri Devender Rao auto asyncResp = std::make_shared<AsyncResp>(res); 795*5968caeeSMarri Devender Rao nlohmann::json &links = 796*5968caeeSMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 797*5968caeeSMarri Devender Rao links = nlohmann::json::array(); 798*5968caeeSMarri Devender Rao getCertificateLocations( 799*5968caeeSMarri Devender Rao asyncResp, 800*5968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 801*5968caeeSMarri Devender Rao certs::httpsObjectPath); 802*5968caeeSMarri Devender Rao } 803*5968caeeSMarri Devender Rao }; // CertificateLocations 804*5968caeeSMarri Devender Rao } // namespace redfish 805