diff options
-rw-r--r-- | Redfish.md | 29 | ||||
-rw-r--r-- | redfish-core/include/utils/collection.hpp | 6 | ||||
-rw-r--r-- | redfish-core/lib/account_service.hpp | 126 |
3 files changed, 160 insertions, 1 deletions
diff --git a/Redfish.md b/Redfish.md index 5e410ad616..cfee9d5110 100644 --- a/Redfish.md +++ b/Redfish.md @@ -62,6 +62,10 @@ Fields common to all schemas - LDAP - MaxPasswordLength - MinPasswordLength +- MultiFactorAuth/ClientCertificate/Certificates +- MultiFactorAuth/ClientCertificate/CertificateMappingAttribute +- MultiFactorAuth/ClientCertificate/Enabled +- MultiFactorAuth/ClientCertificate/RespondToUnauthenticatedClients - Oem/OpenBMC/AuthMethods/BasicAuth - Oem/OpenBMC/AuthMethods/Cookie - Oem/OpenBMC/AuthMethods/SessionToken @@ -70,6 +74,31 @@ Fields common to all schemas - Roles - ServiceEnabled +### /redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates + +- Members +- Members@odata.count + +### /redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates/{Certificate} + +- CertificateString +- Id +- Issuer/City +- Issuer/CommonName +- Issuer/Country +- Issuer/Organization +- Issuer/OrganizationalUnit +- Issuer/State +- KeyUsage +- Subject/City +- Subject/Country +- Subject/CommonName +- Subject/Organization +- Subject/OrganizationalUnit +- Subject/State +- ValidNotAfter +- ValidNotBefore + ### /redfish/v1/AggregationService/ #### AggregationService diff --git a/redfish-core/include/utils/collection.hpp b/redfish-core/include/utils/collection.hpp index 2e5563b4c9..9efa7d3ef3 100644 --- a/redfish-core/include/utils/collection.hpp +++ b/redfish-core/include/utils/collection.hpp @@ -27,6 +27,12 @@ inline void handleCollectionMembers( const boost::system::error_code& ec, const dbus::utility::MapperGetSubTreePathsResponse& objects) { + if (jsonKeyName.empty()) + { + messages::internalError(asyncResp->res); + BMCWEB_LOG_ERROR("Json Key called empty. Did you mean /Members?"); + return; + } nlohmann::json::json_pointer jsonCountKeyName = jsonKeyName; std::string back = jsonCountKeyName.back(); jsonCountKeyName.pop_back(); diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp index 972512b145..1d3ef411a8 100644 --- a/redfish-core/lib/account_service.hpp +++ b/redfish-core/lib/account_service.hpp @@ -16,6 +16,7 @@ #pragma once #include "app.hpp" +#include "certificate_service.hpp" #include "dbus_utility.hpp" #include "error_messages.hpp" #include "generated/enums/account_service.hpp" @@ -23,13 +24,17 @@ #include "persistent_data.hpp" #include "query.hpp" #include "registries/privilege_registry.hpp" +#include "utils/collection.hpp" #include "utils/dbus_utils.hpp" #include "utils/json_utils.hpp" +#include <boost/url/format.hpp> +#include <boost/url/url.hpp> #include <sdbusplus/asio/property.hpp> #include <sdbusplus/unpack_properties.hpp> #include <array> +#include <memory> #include <optional> #include <ranges> #include <string> @@ -1174,6 +1179,80 @@ inline void handleAccountServiceHead( } inline void + getClientCertificates(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const nlohmann::json::json_pointer& keyLocation) +{ + boost::urls::url url( + "/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates"); + std::array<std::string_view, 1> interfaces = { + "xyz.openbmc_project.Certs.Certificate"}; + std::string path = "/xyz/openbmc_project/certs/authority/truststore"; + + collection_util::getCollectionToKey(asyncResp, url, interfaces, path, + keyLocation); +} + +inline void handleAccountServiceClientCertificatesInstanceHead( + App& app, const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& /*id*/) +{ + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + + asyncResp->res.addHeader( + boost::beast::http::field::link, + "</redfish/v1/JsonSchemas/Certificate/Certificate.json>; rel=describedby"); +} + +inline void handleAccountServiceClientCertificatesInstanceGet( + App& app, const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) +{ + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + BMCWEB_LOG_DEBUG("ClientCertificate Certificate ID={}", id); + const boost::urls::url certURL = boost::urls::format( + "/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates/{}", + id); + std::string objPath = + sdbusplus::message::object_path(certs::authorityObjectPath) / id; + getCertificateProperties( + asyncResp, objPath, + "xyz.openbmc_project.Certs.Manager.Authority.Truststore", id, certURL, + "Client Certificate"); +} + +inline void handleAccountServiceClientCertificatesHead( + App& app, const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + + asyncResp->res.addHeader( + boost::beast::http::field::link, + "</redfish/v1/JsonSchemas/CertificateCollection/CertificateCollection.json>; rel=describedby"); +} + +inline void handleAccountServiceClientCertificatesGet( + App& app, const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) +{ + if (!redfish::setUpRedfishRoute(app, req, asyncResp)) + { + return; + } + getClientCertificates(asyncResp, "/Members"_json_pointer); +} + +inline void handleAccountServiceGet(App& app, const crow::Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { @@ -1214,6 +1293,23 @@ inline void allowed.emplace_back(account_service::BasicAuthState::Disabled); json["HTTPBasicAuth@AllowableValues"] = std::move(allowed); + nlohmann::json::object_t clientCertificate; + clientCertificate["Enabled"] = authMethodsConfig.tls; + clientCertificate["RespondToUnauthenticatedClients"] = true; + clientCertificate["CertificateMappingAttribute"] = + account_service::CertificateMappingAttribute::CommonName; + nlohmann::json::object_t certificates; + certificates["@odata.id"] = + "/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates"; + certificates["@odata.type"] = + "#CertificateCollection.CertificateCollection"; + clientCertificate["Certificates"] = std::move(certificates); + json["MultiFactorAuth"]["ClientCertificate"] = std::move(clientCertificate); + + getClientCertificates( + asyncResp, + "/MultiFactorAuth/ClientCertificate/Certificates/Members"_json_pointer); + json["Oem"]["OpenBMC"]["@odata.type"] = "#OpenBMCAccountService.v1_0_0.AccountService"; json["Oem"]["OpenBMC"]["@odata.id"] = @@ -1249,7 +1345,7 @@ inline void return; } - BMCWEB_LOG_DEBUG("Got {}properties for AccountService", + BMCWEB_LOG_DEBUG("Got {} properties for AccountService", propertiesList.size()); const uint8_t* minPasswordLength = nullptr; @@ -2026,6 +2122,34 @@ inline void requestAccountServiceRoutes(App& app) .methods(boost::beast::http::verb::patch)( std::bind_front(handleAccountServicePatch, std::ref(app))); + BMCWEB_ROUTE( + app, + "/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates") + .privileges(redfish::privileges::headCertificateCollection) + .methods(boost::beast::http::verb::head)(std::bind_front( + handleAccountServiceClientCertificatesHead, std::ref(app))); + + BMCWEB_ROUTE( + app, + "/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates") + .privileges(redfish::privileges::getCertificateCollection) + .methods(boost::beast::http::verb::get)(std::bind_front( + handleAccountServiceClientCertificatesGet, std::ref(app))); + + BMCWEB_ROUTE( + app, + "/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates/<str>") + .privileges(redfish::privileges::headCertificate) + .methods(boost::beast::http::verb::head)(std::bind_front( + handleAccountServiceClientCertificatesInstanceHead, std::ref(app))); + + BMCWEB_ROUTE( + app, + "/redfish/v1/AccountService/MultiFactorAuth/ClientCertificate/Certificates/<str>/") + .privileges(redfish::privileges::getCertificate) + .methods(boost::beast::http::verb::get)(std::bind_front( + handleAccountServiceClientCertificatesInstanceGet, std::ref(app))); + BMCWEB_ROUTE(app, "/redfish/v1/AccountService/Accounts/") .privileges(redfish::privileges::headManagerAccountCollection) .methods(boost::beast::http::verb::head)( |