Modify entityPrivileges for certificate service
DMTF published new entity privileges for certificate service classes
which modify entity privilege Certificate, CertificateCollection,
CertificateLocations, and CertificateService on bmcweb. Modification
restricts a user without "ConfigureManager" from accessing the
CertificateCollection and Certificate scehamas
Redfish is a hypermedia API where the parent URI describes sub-URI.
Thus, restricting sub-URI in a parent-URI data helps to forbidden user
access, stricken the rule. So sub-URI only gets display if a user has
access to that URI.
Restricting the link allows the Redfish Validator to pass.
These impact roles without ConfigureManager, which include operator
and read-only. No access is not impacted since it already did not
have access.
The following are bmcweb user consequences:
1. ReadOnly and Operator role users are no longer able to view
certificates or the certificate collection (LDAP, HTTPS, TrustStore)
2. Operator role users are no longer able to replace the certificates
(LDAP, HTTPS, TrustStore), Install certificates (LDAP, HTTPS,
TrustStore) or delete the Truststore Certificate. HTTPS and LDAP
certificates do not have delete methods.
Resolves openbmc/bmcweb#61
Tested: manually tested on Witherspoon system and run Redfish-Service-
Validator with all roles root, operator, read-only, and No access. Test
pass for root, operator, and read-only roles, And new errors get
introduced for no access role.
Signed-off-by: Abhishek Patel <Abhishek.Patel@ibm.com>
Change-Id: Ibc5eed7db7e224e46f8572df8bcfba2a1ff47644
diff --git a/redfish-core/lib/account_service.hpp b/redfish-core/lib/account_service.hpp
index 835fae3..364d5e2 100644
--- a/redfish-core/lib/account_service.hpp
+++ b/redfish-core/lib/account_service.hpp
@@ -1258,7 +1258,7 @@
BMCWEB_ROUTE(app, "/redfish/v1/AccountService/")
.privileges({{"Login"}})
.methods(
- boost::beast::http::verb::get)([](const crow::Request& /* req */,
+ boost::beast::http::verb::get)([](const crow::Request& req,
const std::shared_ptr<
bmcweb::AsyncResp>& asyncResp)
-> void {
@@ -1288,11 +1288,21 @@
{"XToken", authMethodsConfig.xtoken},
{"Cookie", authMethodsConfig.cookie},
{"TLS", authMethodsConfig.tls},
- }}}}}},
- {"LDAP",
- {{"Certificates",
- {{"@odata.id",
- "/redfish/v1/AccountService/LDAP/Certificates"}}}}}};
+ }}}}}}};
+ // /redfish/v1/AccountService/LDAP/Certificates is something only
+ // ConfigureManager can access then only display when the user has
+ // permissions ConfigureManager
+ Privileges effectiveUserPrivileges =
+ redfish::getUserPrivileges(req.userRole);
+
+ if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
+ effectiveUserPrivileges))
+ {
+ asyncResp->res.jsonValue["LDAP"] = {
+ {"Certificates",
+ {{"@odata.id",
+ "/redfish/v1/AccountService/LDAP/Certificates"}}}};
+ }
crow::connections::systemBus->async_method_call(
[asyncResp](
const boost::system::error_code ec,
diff --git a/redfish-core/lib/certificate_service.hpp b/redfish-core/lib/certificate_service.hpp
index c1861ca..6eb66c5 100644
--- a/redfish-core/lib/certificate_service.hpp
+++ b/redfish-core/lib/certificate_service.hpp
@@ -43,31 +43,39 @@
{
BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
.privileges({{"Login"}})
- .methods(boost::beast::http::verb::get)(
- [](const crow::Request&,
- const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- asyncResp->res.jsonValue = {
- {"@odata.type",
- "#CertificateService.v1_0_0.CertificateService"},
- {"@odata.id", "/redfish/v1/CertificateService"},
- {"Id", "CertificateService"},
- {"Name", "Certificate Service"},
- {"Description",
- "Actions available to manage certificates"}};
+ .methods(
+ boost::beast::http::verb::
+ get)([](const crow::Request& req,
+ const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
+ asyncResp->res.jsonValue = {
+ {"@odata.type",
+ "#CertificateService.v1_0_0.CertificateService"},
+ {"@odata.id", "/redfish/v1/CertificateService"},
+ {"Id", "CertificateService"},
+ {"Name", "Certificate Service"},
+ {"Description", "Actions available to manage certificates"}};
+ // /redfish/v1/CertificateService/CertificateLocations is something
+ // only ConfigureManager can access then only display when the user
+ // has permissions ConfigureManager
+ Privileges effectiveUserPrivileges =
+ redfish::getUserPrivileges(req.userRole);
+ if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
+ effectiveUserPrivileges))
+ {
asyncResp->res.jsonValue["CertificateLocations"] = {
{"@odata.id",
"/redfish/v1/CertificateService/CertificateLocations"}};
- asyncResp->res
- .jsonValue["Actions"]
- ["#CertificateService.ReplaceCertificate"] = {
- {"target", "/redfish/v1/CertificateService/Actions/"
- "CertificateService.ReplaceCertificate"},
- {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
- asyncResp->res
- .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
- {"target", "/redfish/v1/CertificateService/Actions/"
- "CertificateService.GenerateCSR"}};
- });
+ }
+ asyncResp->res.jsonValue["Actions"]
+ ["#CertificateService.ReplaceCertificate"] =
+ {{"target", "/redfish/v1/CertificateService/Actions/"
+ "CertificateService.ReplaceCertificate"},
+ {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
+ asyncResp->res
+ .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
+ {"target", "/redfish/v1/CertificateService/Actions/"
+ "CertificateService.GenerateCSR"}};
+ });
} // requestRoutesCertificateService
/**
@@ -667,7 +675,7 @@
{
BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
"CertificateService.ReplaceCertificate/")
- .privileges({{"ConfigureComponents"}})
+ .privileges({{"ConfigureManager"}})
.methods(
boost::beast::http::verb::
post)([](const crow::Request& req,
@@ -785,7 +793,7 @@
BMCWEB_ROUTE(
app,
"/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
- .privileges({{"Login"}})
+ .privileges({{"ConfigureManager"}})
.methods(
boost::beast::http::verb::
get)([](const crow::Request& req,
@@ -819,7 +827,7 @@
{
BMCWEB_ROUTE(app,
"/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
- .privileges({{"Login"}})
+ .privileges({{"ConfigureManager"}})
.methods(
boost::beast::http::verb::
get)([](const crow::Request&,
@@ -864,7 +872,7 @@
BMCWEB_ROUTE(app,
"/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
- .privileges({{"ConfigureComponents"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::post)(
[](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
@@ -971,7 +979,7 @@
inline void requestRoutesCertificateLocations(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
- .privileges({{"Login"}})
+ .privileges({{"ConfigureManager"}})
.methods(
boost::beast::http::verb::
get)([](const crow::Request&,
@@ -1010,7 +1018,7 @@
inline void requestRoutesLDAPCertificateCollection(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
- .privileges({{"Login"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::get)(
[](const crow::Request&,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
@@ -1056,7 +1064,7 @@
});
BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
- .privileges({{"ConfigureComponents"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::post)(
[](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
@@ -1113,7 +1121,7 @@
inline void requestRoutesLDAPCertificate(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
- .privileges({{"Login"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::get)(
[](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -1144,7 +1152,7 @@
inline void requestRoutesTrustStoreCertificateCollection(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
- .privileges({{"Login"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::get)(
[](const crow::Request&,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
@@ -1188,7 +1196,7 @@
});
BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
- .privileges({{"ConfigureComponents"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::post)(
[](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
@@ -1246,7 +1254,7 @@
inline void requestRoutesTrustStoreCertificate(App& app)
{
BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
- .privileges({{"Loign"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::get)(
[](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
@@ -1272,7 +1280,7 @@
});
BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
- .privileges({{"ConfigureComponents"}})
+ .privileges({{"ConfigureManager"}})
.methods(boost::beast::http::verb::delete_)(
[](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
diff --git a/redfish-core/lib/network_protocol.hpp b/redfish-core/lib/network_protocol.hpp
index d82c252..daa1965 100644
--- a/redfish-core/lib/network_protocol.hpp
+++ b/redfish-core/lib/network_protocol.hpp
@@ -128,7 +128,8 @@
"org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
}
-void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
+void getNetworkData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+ const crow::Request& req)
{
asyncResp->res.jsonValue["@odata.type"] =
"#ManagerNetworkProtocol.v1_5_0.ManagerNetworkProtocol";
@@ -186,19 +187,29 @@
}
});
+ Privileges effectiveUserPrivileges =
+ redfish::getUserPrivileges(req.userRole);
+
crow::connections::systemBus->async_method_call(
- [asyncResp](const boost::system::error_code e,
- const std::vector<UnitStruct>& r) {
+ [asyncResp,
+ &effectiveUserPrivileges](const boost::system::error_code e,
+ const std::vector<UnitStruct>& r) {
if (e)
{
asyncResp->res.jsonValue = nlohmann::json::object();
messages::internalError(asyncResp->res);
return;
}
- asyncResp->res.jsonValue["HTTPS"]["Certificates"] = {
- {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol/"
- "HTTPS/Certificates"}};
-
+ // /redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates is
+ // something only ConfigureManager can access then only display when
+ // the user has permissions ConfigureManager
+ if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
+ effectiveUserPrivileges))
+ {
+ asyncResp->res.jsonValue["HTTPS"]["Certificates"] = {
+ {"@odata.id", "/redfish/v1/Managers/bmc/NetworkProtocol/"
+ "HTTPS/Certificates"}};
+ }
for (auto& unit : r)
{
/* Only traverse through <xyz>.socket units */
@@ -541,9 +552,9 @@
BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/NetworkProtocol/")
.privileges({{"Login"}})
.methods(boost::beast::http::verb::get)(
- [](const crow::Request&,
+ [](const crow::Request& req,
const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
- getNetworkData(asyncResp);
+ getNetworkData(asyncResp, req);
});
}