diff options
author | Marri Devender Rao <devenrao@in.ibm.com> | 2019-02-20 10:05:22 +0300 |
---|---|---|
committer | Ed Tanous <ed.tanous@intel.com> | 2019-07-03 19:24:11 +0300 |
commit | 37cce918ede6489ab980712c243b526a30396ca4 (patch) | |
tree | 5874c52f670e2c4dbf6d2e2a6f9601bd39c2a1a1 /redfish-core/lib/certificate_service.hpp | |
parent | 6913228d184308c9e848a5cf60ce9b8d2cb44aee (diff) | |
download | bmcweb-37cce918ede6489ab980712c243b526a30396ca4.tar.xz |
Redfish: Add support to upload/replace/view LDAP Certificate
Implements CertificateCollection schema to upload/list
existing LDAP certificates
Implements Certificate schema to view existing LDAP
certificate
Implements ReplaceCertificate action to replace existing
LDAP certificate.
Tested:
1. Tested schema with validator and no issues
2. Privilege map for certificate service is not yet pubished
3. POST on /redfish/v1/AccountService/LDAP/Certificates
curl -c cjar -b cjar -k -H "X-Auth-Token: $bmc_token" -H "Content-Type: application/octet-stream" -X POST -T testcert.pem https://${bmc}/redfish/v1/AccountServie/LDAP/Certificates
{
"@odata.context": "/redfish/v1/$metadata#Certificate.Certificate",
"@odata.id": "/redfish/v1/AccountService/LDAP/Certificates/1",
"@odata.type": "#Certificate.v1_0_0.Certificate",
"CertificateString": "-----BEGIN CERTIFICATE---------END CERTIFICATE-----\n",
"Description": "LDAP Certificate",
"Id": "1",
"Issuer": {
"City": "SomeCity",
"CommonName": "www.company.com",
"Country": "US",
"Organization": "MyCompany",
"State": "VA",
"organizationUnit": "MyDivision"
},
"KeyUsage": [
"KeyAgreement",
"ServerAuthentication"
],
"Name": "LDAP Certificate",
"Subject": {
"City": "SomeCity",
"CommonName": "www.company.com",
"Organization": "MyCompany",
"State": "VA",
"organizationUnit": "MyDivision"
},
"ValidNotAfter": "2029-03-14T02:11:02+00:00",
"ValidNotBefore": "2019-03-17T02:11:02+00:00"
}
4. GET on /redfish/v1/AccountService/LDAP/Certificates/
{
"@odata.context":
"/redfish/v1/$metadata#CertificateCollection.CertificateCollection",
"@odata.id": "/redfish/v1/AccountService/LDAP/Certificates",
"@odata.type": "#CertificateCollection.CertificatesCollection",
"Description": "A Collection of LDAP certificate instances",
"Members": [
{
"@odata.id": "/redfish/v1/AccountService/LDAP/Certificates/1"
}
],
"Members@odata.count": 1,
"Name": "LDAP Certificate Collection"
}
5.GET on /redfish/v1/CertificateService/CertificateLocations/
{
"@odata.context":
"/redfish/v1/$metadata#CertificateLocations.CertificateLocations",
"@odata.id": "/redfish/v1/CertificateService/CertificateLocations",
"@odata.type": "#CertificateLocations.v1_0_0.CertificateLocations",
"Description": "Defines a resource that an administrator can use in order to
locate all certificates installed on a given service",
"Id": "CertificateLocations",
"Links": {
"Certificates": [
{
"@odata.id":
"/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/1"
},
{
"@odata.id": "/redfish/v1/AccountService/LDAP/Certificates/1"
}
],
"Certificates@odata.count": 2
},
"Name": "Certificate Locations"
}
6.GET on /redfish/v1/AccountService/LDAP/Certificates/1
{
"@odata.context": "/redfish/v1/$metadata#Certificate.Certificate",
"@odata.id": "/redfish/v1/AccountService/LDAP/Certificates/1",
"@odata.type": "#Certificate.v1_0_0.Certificate",
"CertificateString": "-----BEGINCERTIFICATE-----\n ... -----ENDCERTIFICATE-----\n",
"CertificateType": "PEM",
"Description": "LDAP Certificate",
"Id": "1",
"Issuer": {
"CommonName": "localhost",
"Organization": "openbmc-project.xyz"
},
"KeyUsage": [],
"Name": "LDAP Certificate",
"Subject": {
"CommonName": "localhost"
}
7.Replace certificate
POST on /redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/
{
"@odata.context": "/redfish/v1/$metadata#Certificate.Certificate",
"@odata.id": "/redfish/v1/AccountService/LDAP/Certificates/1",
"@odata.type": "#Certificate.v1_0_0.Certificate",
...
}
8.GET on AccountService
curl -k -H "X-Auth-Token: $bmc_token" -X GET
https://${bmc}/redfish/v1/AccountService
{
"@odata.context": "/redfish/v1/$metadata#AccountService.AccountService",
"@odata.id": "/redfish/v1/AccountService",
"@odata.type": "#AccountService.v1_4_0.AccountService",
"Id": "AccountService",
"LDAP": {
"AccountProviderType": "LDAPService",
"Certificates": {
"@odata.id": "/redfish/v1/AccountService/LDAP/Certificates"
},
Change-Id: I056a4cea8b0377e156b660984857cdfadbfe1b2c
Signed-off-by: Marri Devender Rao <devenrao@in.ibm.com>
Diffstat (limited to 'redfish-core/lib/certificate_service.hpp')
-rw-r--r-- | redfish-core/lib/certificate_service.hpp | 603 |
1 files changed, 317 insertions, 286 deletions
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp index 8045e4ea91..4a077c880b 100644 --- a/redfish-core/lib/certificate_service.hpp +++ b/redfish-core/lib/certificate_service.hpp @@ -32,6 +32,11 @@ constexpr char const *dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; constexpr char const *mapperBusName = "xyz.openbmc_project.ObjectMapper"; constexpr char const *mapperObjectPath = "/xyz/openbmc_project/object_mapper"; constexpr char const *mapperIntf = "xyz.openbmc_project.ObjectMapper"; +constexpr char const *ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; +constexpr char const *httpsServiceName = + "xyz.openbmc_project.Certs.Manager.Server.Https"; +constexpr char const *ldapServiceName = + "xyz.openbmc_project.Certs.Manager.Client.Ldap"; } // namespace certs /** @@ -80,6 +85,7 @@ class CertificateService : public Node res.end(); } }; // CertificateService + /** * @brief Find the ID specified in the URL * Finds the numbers specified after the last "/" in the URL and returns. @@ -98,7 +104,7 @@ long getIDFromURL(const std::string_view url) char *endPtr; std::string_view str = url.substr(found + 1); long value = std::strtol(str.data(), &endPtr, 10); - if (endPtr != &str.back()) + if (endPtr != str.end()) { return -1; } @@ -237,7 +243,8 @@ static void updateCertIssuerOrSubject(nlohmann::json &out, */ static void getCertificateProperties( const std::shared_ptr<AsyncResp> &asyncResp, const std::string &objectPath, - long certId, const std::string &certURL, const std::string &name) + const std::string &service, long certId, const std::string &certURL, + const std::string &name) { using PropertyType = std::variant<std::string, uint64_t, std::vector<std::string>>; @@ -245,123 +252,96 @@ static void getCertificateProperties( BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath << " certId=" << certId << " certURl=" << certURL; crow::connections::systemBus->async_method_call( - [asyncResp, objectPath, certURL, certId, - name](const boost::system::error_code ec, const GetObjectType &resp) { + [asyncResp, certURL, certId, name](const boost::system::error_code ec, + const PropertiesMap &properties) { if (ec) { BMCWEB_LOG_ERROR << "DBUS response error: " << ec; messages::internalError(asyncResp->res); return; } - if (resp.size() > 1 || resp.empty()) + asyncResp->res.jsonValue = { + {"@odata.id", certURL}, + {"@odata.type", "#Certificate.v1_0_0.Certificate"}, + {"@odata.context", + "/redfish/v1/$metadata#Certificate.Certificate"}, + {"Id", std::to_string(certId)}, + {"Name", name}, + {"Description", name}}; + for (const auto &property : properties) { - BMCWEB_LOG_ERROR << "Invalid number of objects found " - << resp.size(); - messages::internalError(asyncResp->res); - return; - } - const std::string &service = resp.begin()->first; - crow::connections::systemBus->async_method_call( - [asyncResp, certURL, certId, - name](const boost::system::error_code ec, - const PropertiesMap &properties) { - if (ec) + if (property.first == "CertificateString") + { + asyncResp->res.jsonValue["CertificateString"] = ""; + const std::string *value = + std::get_if<std::string>(&property.second); + if (value) { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; + asyncResp->res.jsonValue["CertificateString"] = *value; } - asyncResp->res.jsonValue = { - {"@odata.id", certURL}, - {"@odata.type", "#Certificate.v1_0_0.Certificate"}, - {"@odata.context", - "/redfish/v1/$metadata#Certificate.Certificate"}, - {"Id", std::to_string(certId)}, - {"Name", name}, - {"Description", name}}; - for (const auto &property : properties) + } + else if (property.first == "KeyUsage") + { + nlohmann::json &keyUsage = + asyncResp->res.jsonValue["KeyUsage"]; + keyUsage = nlohmann::json::array(); + const std::vector<std::string> *value = + std::get_if<std::vector<std::string>>(&property.second); + if (value) { - if (property.first == "CertificateString") - { - asyncResp->res.jsonValue["CertificateString"] = ""; - const std::string *value = - std::get_if<std::string>(&property.second); - if (value) - { - asyncResp->res.jsonValue["CertificateString"] = - *value; - } - } - else if (property.first == "KeyUsage") - { - nlohmann::json &keyUsage = - asyncResp->res.jsonValue["KeyUsage"]; - keyUsage = nlohmann::json::array(); - const std::vector<std::string> *value = - std::get_if<std::vector<std::string>>( - &property.second); - if (value) - { - for (const std::string &usage : *value) - { - keyUsage.push_back(usage); - } - } - } - else if (property.first == "Issuer") - { - const std::string *value = - std::get_if<std::string>(&property.second); - if (value) - { - updateCertIssuerOrSubject( - asyncResp->res.jsonValue["Issuer"], *value); - } - } - else if (property.first == "Subject") + for (const std::string &usage : *value) { - const std::string *value = - std::get_if<std::string>(&property.second); - if (value) - { - updateCertIssuerOrSubject( - asyncResp->res.jsonValue["Subject"], - *value); - } - } - else if (property.first == "ValidNotAfter") - { - const uint64_t *value = - std::get_if<uint64_t>(&property.second); - if (value) - { - std::time_t time = - static_cast<std::time_t>(*value); - asyncResp->res.jsonValue["ValidNotAfter"] = - crow::utility::getDateTime(time); - } - } - else if (property.first == "ValidNotBefore") - { - const uint64_t *value = - std::get_if<uint64_t>(&property.second); - if (value) - { - std::time_t time = - static_cast<std::time_t>(*value); - asyncResp->res.jsonValue["ValidNotBefore"] = - crow::utility::getDateTime(time); - } + keyUsage.push_back(usage); } } - asyncResp->res.addHeader("Location", certURL); - }, - service, objectPath, certs::dbusPropIntf, "GetAll", - certs::certPropIntf); + } + else if (property.first == "Issuer") + { + const std::string *value = + std::get_if<std::string>(&property.second); + if (value) + { + updateCertIssuerOrSubject( + asyncResp->res.jsonValue["Issuer"], *value); + } + } + else if (property.first == "Subject") + { + const std::string *value = + std::get_if<std::string>(&property.second); + if (value) + { + updateCertIssuerOrSubject( + asyncResp->res.jsonValue["Subject"], *value); + } + } + else if (property.first == "ValidNotAfter") + { + const uint64_t *value = + std::get_if<uint64_t>(&property.second); + if (value) + { + std::time_t time = static_cast<std::time_t>(*value); + asyncResp->res.jsonValue["ValidNotAfter"] = + crow::utility::getDateTime(time); + } + } + else if (property.first == "ValidNotBefore") + { + const uint64_t *value = + std::get_if<uint64_t>(&property.second); + if (value) + { + std::time_t time = static_cast<std::time_t>(*value); + asyncResp->res.jsonValue["ValidNotBefore"] = + crow::utility::getDateTime(time); + } + } + } + asyncResp->res.addHeader("Location", certURL); }, - certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, - "GetObject", objectPath, - std::array<const char *, 1>{certs::certPropIntf}); + service, objectPath, certs::dbusPropIntf, "GetAll", + certs::certPropIntf); } using GetObjectType = @@ -424,17 +404,6 @@ class CertificateActionsReplaceCertificate : public Node return; } - if (!boost::starts_with( - certURI, - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) - { - BMCWEB_LOG_ERROR << "Unsupported certificate URI" << certURI; - messages::actionParameterValueFormatError(asyncResp->res, certURI, - "CertificateUri", - "ReplaceCertificate"); - return; - } - BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; long id = getIDFromURL(certURI); if (id < 0) @@ -446,6 +415,7 @@ class CertificateActionsReplaceCertificate : public Node } std::string objectPath; std::string name; + std::string service; if (boost::starts_with( certURI, "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) @@ -453,6 +423,15 @@ class CertificateActionsReplaceCertificate : public Node objectPath = std::string(certs::httpsObjectPath) + "/" + std::to_string(id); name = "HTTPS certificate"; + service = certs::httpsServiceName; + } + else if (boost::starts_with( + certURI, "/redfish/v1/AccountService/LDAP/Certificates/")) + { + objectPath = + std::string(certs::ldapObjectPath) + "/" + std::to_string(id); + name = "LDAP certificate"; + service = certs::ldapServiceName; } else { @@ -463,44 +442,22 @@ class CertificateActionsReplaceCertificate : public Node std::shared_ptr<CertificateFile> certFile = std::make_shared<CertificateFile>(certificate); - crow::connections::systemBus->async_method_call( - [asyncResp, objectPath, certFile, id, certURI, name]( - const boost::system::error_code ec, const GetObjectType &resp) { + [asyncResp, certFile, objectPath, service, certURI, id, + name](const boost::system::error_code ec) { if (ec) { BMCWEB_LOG_ERROR << "DBUS response error: " << ec; messages::internalError(asyncResp->res); return; } - if (resp.size() > 1 || resp.empty()) - { - BMCWEB_LOG_ERROR << "Invalid number of objects found " - << resp.size(); - messages::internalError(asyncResp->res); - return; - } - const std::string &service = resp.begin()->first; - crow::connections::systemBus->async_method_call( - [asyncResp, certFile, objectPath, certURI, id, - name](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; - } - getCertificateProperties(asyncResp, objectPath, id, - certURI, name); - BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" - << certFile->getCertFilePath(); - }, - service, objectPath, certs::certReplaceIntf, "Replace", - certFile->getCertFilePath()); + getCertificateProperties(asyncResp, objectPath, service, id, + certURI, name); + BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" + << certFile->getCertFilePath(); }, - certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, - "GetObject", objectPath, - std::array<std::string, 1>({certs::certReplaceIntf})); + service, objectPath, certs::certReplaceIntf, "Replace", + certFile->getCertFilePath()); } }; // CertificateActionsReplaceCertificate @@ -545,8 +502,8 @@ class HTTPSCertificate : public Node std::string objectPath = certs::httpsObjectPath; objectPath += "/"; objectPath += std::to_string(id); - getCertificateProperties(asyncResp, objectPath, id, certURL, - "HTTPS Certificate"); + getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName, + id, certURL, "HTTPS Certificate"); } }; // namespace redfish @@ -585,54 +542,32 @@ class HTTPSCertificateCollection : public Node auto asyncResp = std::make_shared<AsyncResp>(res); crow::connections::systemBus->async_method_call( [asyncResp](const boost::system::error_code ec, - const GetObjectType &resp) { + const ManagedObjectType &certs) { if (ec) { BMCWEB_LOG_ERROR << "DBUS response error: " << ec; messages::internalError(asyncResp->res); return; } - if (resp.size() > 1 || resp.empty()) + nlohmann::json &members = asyncResp->res.jsonValue["Members"]; + members = nlohmann::json::array(); + for (const auto &cert : certs) { - BMCWEB_LOG_ERROR << "Invalid number of objects found " - << resp.size(); - messages::internalError(asyncResp->res); - return; + long id = getIDFromURL(cert.first.str); + if (id >= 0) + { + members.push_back( + {{"@odata.id", + "/redfish/v1/Managers/bmc/" + "NetworkProtocol/HTTPS/Certificates/" + + std::to_string(id)}}); + } } - const std::string &service = resp.begin()->first; - crow::connections::systemBus->async_method_call( - [asyncResp](const boost::system::error_code ec, - const ManagedObjectType &certs) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; - } - nlohmann::json &members = - asyncResp->res.jsonValue["Members"]; - members = nlohmann::json::array(); - for (const auto &cert : certs) - { - long id = getIDFromURL(cert.first.str); - if (id != -1) - { - members.push_back( - {{"@odata.id", - "/redfish/v1/Managers/bmc/" - "NetworkProtocol/HTTPS/Certificates/" + - std::to_string(id)}}); - } - } - asyncResp->res.jsonValue["Members@odata.count"] = - members.size(); - }, - service, certs::httpsObjectPath, certs::dbusObjManagerIntf, - "GetManagedObjects"); + asyncResp->res.jsonValue["Members@odata.count"] = + members.size(); }, - certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, - "GetObject", certs::httpsObjectPath, - std::array<const char *, 1>{certs::certInstallIntf}); + certs::httpsServiceName, certs::httpsObjectPath, + certs::dbusObjManagerIntf, "GetManagedObjects"); } void doPost(crow::Response &res, const crow::Request &req, @@ -647,115 +582,33 @@ class HTTPSCertificateCollection : public Node std::make_shared<CertificateFile>(req.body); crow::connections::systemBus->async_method_call( - [asyncResp, certFile](const boost::system::error_code ec, - const GetObjectType &resp) { + [asyncResp, certFile](const boost::system::error_code ec) { if (ec) { BMCWEB_LOG_ERROR << "DBUS response error: " << ec; messages::internalError(asyncResp->res); return; } - if (resp.size() > 1 || resp.empty()) - { - BMCWEB_LOG_ERROR << "Invalid number of objects found " - << resp.size(); - messages::internalError(asyncResp->res); - return; - } - const std::string &service = resp.begin()->first; - crow::connections::systemBus->async_method_call( - [asyncResp, certFile](const boost::system::error_code ec) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; - } - // TODO: Issue#84 supporting only 1 certificate - long certId = 1; - std::string certURL = - "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/" - "Certificates/" + - std::to_string(certId); - std::string objectPath = - std::string(certs::httpsObjectPath) + "/" + - std::to_string(certId); - getCertificateProperties(asyncResp, objectPath, certId, - certURL, "HTTPS Certificate"); - BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" - << certFile->getCertFilePath(); - }, - service, certs::httpsObjectPath, certs::certInstallIntf, - "Install", certFile->getCertFilePath()); + // TODO: Issue#84 supporting only 1 certificate + long certId = 1; + std::string certURL = + "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/" + "Certificates/" + + std::to_string(certId); + std::string objectPath = std::string(certs::httpsObjectPath) + + "/" + std::to_string(certId); + getCertificateProperties(asyncResp, objectPath, + certs::httpsServiceName, certId, + certURL, "HTTPS Certificate"); + BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" + << certFile->getCertFilePath(); }, - certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, - "GetObject", certs::httpsObjectPath, - std::array<const char *, 1>{certs::certInstallIntf}); + certs::httpsServiceName, certs::httpsObjectPath, + certs::certInstallIntf, "Install", certFile->getCertFilePath()); } }; // HTTPSCertificateCollection /** - * @brief Retrieve the certificates installed list and append to the response - * - * @param[in] asyncResp Shared pointer to the response message - * @param[in] certURL Path of the certificate object - * @param[in] path Path of the D-Bus service object - * @return None - */ -static void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp, - const std::string &certURL, - const std::string &path) -{ - BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL - << " Path=" << path; - crow::connections::systemBus->async_method_call( - [asyncResp, path, certURL](const boost::system::error_code ec, - const GetObjectType &resp) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; - } - if (resp.size() > 1 || resp.empty()) - { - BMCWEB_LOG_ERROR << "Invalid number of objects found " - << resp.size(); - messages::internalError(asyncResp->res); - return; - } - const std::string &service = resp.begin()->first; - crow::connections::systemBus->async_method_call( - [asyncResp, certURL](const boost::system::error_code ec, - const ManagedObjectType &certs) { - if (ec) - { - BMCWEB_LOG_ERROR << "DBUS response error: " << ec; - messages::internalError(asyncResp->res); - return; - } - nlohmann::json &links = - asyncResp->res.jsonValue["Links"]["Certificates"]; - for (auto &cert : certs) - { - long id = getIDFromURL(cert.first.str); - if (id != -1) - { - links.push_back( - {{"@odata.id", certURL + std::to_string(id)}}); - } - } - asyncResp->res - .jsonValue["Links"]["Certificates@odata.count"] = - links.size(); - }, - service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); - }, - certs::mapperBusName, certs::mapperObjectPath, certs::mapperIntf, - "GetObject", path, std::array<std::string, 0>()); -} - -/** * The certificate location schema defines a resource that an administrator * can use in order to locate all certificates installed on a given service. */ @@ -798,7 +651,185 @@ class CertificateLocations : public Node getCertificateLocations( asyncResp, "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", - certs::httpsObjectPath); + certs::httpsObjectPath, certs::httpsServiceName); + getCertificateLocations(asyncResp, + "/redfish/v1/AccountService/LDAP/Certificates/", + certs::ldapObjectPath, certs::ldapServiceName); + } + /** + * @brief Retrieve the certificates installed list and append to the + * response + * + * @param[in] asyncResp Shared pointer to the response message + * @param[in] certURL Path of the certificate object + * @param[in] path Path of the D-Bus service object + * @return None + */ + void getCertificateLocations(std::shared_ptr<AsyncResp> &asyncResp, + const std::string &certURL, + const std::string &path, + const std::string &service) + { + BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL + << " Path=" << path << " service= " << service; + crow::connections::systemBus->async_method_call( + [asyncResp, certURL](const boost::system::error_code ec, + const ManagedObjectType &certs) { + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); + return; + } + nlohmann::json &links = + asyncResp->res.jsonValue["Links"]["Certificates"]; + for (auto &cert : certs) + { + long id = getIDFromURL(cert.first.str); + if (id >= 0) + { + links.push_back( + {{"@odata.id", certURL + std::to_string(id)}}); + } + } + asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = + links.size(); + }, + service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); } }; // CertificateLocations + +/** + * Collection of LDAP certificates + */ +class LDAPCertificateCollection : public Node +{ + public: + template <typename CrowApp> + LDAPCertificateCollection(CrowApp &app) : + Node(app, "/redfish/v1/AccountService/LDAP/Certificates/") + { + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; + } + void doGet(crow::Response &res, const crow::Request &req, + const std::vector<std::string> ¶ms) override + { + res.jsonValue = { + {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, + {"@odata.type", "#CertificateCollection.CertificateCollection"}, + {"@odata.context", + "/redfish/v1/" + "$metadata#CertificateCollection.CertificateCollection"}, + {"Name", "LDAP Certificates Collection"}, + {"Description", "A Collection of LDAP certificate instances"}}; + auto asyncResp = std::make_shared<AsyncResp>(res); + crow::connections::systemBus->async_method_call( + [asyncResp](const boost::system::error_code ec, + const ManagedObjectType &certs) { + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); + return; + } + nlohmann::json &members = asyncResp->res.jsonValue["Members"]; + members = nlohmann::json::array(); + for (const auto &cert : certs) + { + long id = getIDFromURL(cert.first.str); + if (id >= 0) + { + members.push_back( + {{"@odata.id", "/redfish/v1/AccountService/" + "LDAP/Certificates/" + + std::to_string(id)}}); + } + } + asyncResp->res.jsonValue["Members@odata.count"] = + members.size(); + }, + certs::ldapServiceName, certs::ldapObjectPath, + certs::dbusObjManagerIntf, "GetManagedObjects"); + } + + void doPost(crow::Response &res, const crow::Request &req, + const std::vector<std::string> ¶ms) override + { + std::shared_ptr<CertificateFile> certFile = + std::make_shared<CertificateFile>(req.body); + auto asyncResp = std::make_shared<AsyncResp>(res); + crow::connections::systemBus->async_method_call( + [asyncResp, certFile](const boost::system::error_code ec) { + if (ec) + { + BMCWEB_LOG_ERROR << "DBUS response error: " << ec; + messages::internalError(asyncResp->res); + return; + } + //// TODO: Issue#84 supporting only 1 certificate + long certId = 1; + std::string certURL = + "/redfish/v1/AccountService/LDAP/Certificates/" + + std::to_string(certId); + std::string objectPath = std::string(certs::ldapObjectPath) + + "/" + std::to_string(certId); + getCertificateProperties(asyncResp, objectPath, + certs::ldapServiceName, certId, + certURL, "LDAP Certificate"); + BMCWEB_LOG_DEBUG << "LDAP certificate install file=" + << certFile->getCertFilePath(); + }, + certs::ldapServiceName, certs::ldapObjectPath, + certs::certInstallIntf, "Install", certFile->getCertFilePath()); + } +}; // LDAPCertificateCollection + +/** + * Certificate resource describes a certificate used to prove the identity + * of a component, account or service. + */ +class LDAPCertificate : public Node +{ + public: + template <typename CrowApp> + LDAPCertificate(CrowApp &app) : + Node(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/", + std::string()) + { + entityPrivileges = { + {boost::beast::http::verb::get, {{"Login"}}}, + {boost::beast::http::verb::head, {{"Login"}}}, + {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, + {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; + } + + void doGet(crow::Response &res, const crow::Request &req, + const std::vector<std::string> ¶ms) override + { + auto asyncResp = std::make_shared<AsyncResp>(res); + long id = getIDFromURL(req.url); + if (id < 0) + { + BMCWEB_LOG_ERROR << "Invalid url value" << req.url; + messages::internalError(asyncResp->res); + return; + } + BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id); + std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" + + std::to_string(id); + std::string objectPath = certs::ldapObjectPath; + objectPath += "/"; + objectPath += std::to_string(id); + getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, + id, certURL, "LDAP Certificate"); + } +}; // LDAPCertificate } // namespace redfish |