diff options
| author | Borawski.Lukasz <lukasz.borawski@intel.com> | 2018-01-25 12:14:14 +0100 |
|---|---|---|
| committer | Ed Tanous <ed.tanous@intel.com> | 2018-03-27 21:02:27 +0000 |
| commit | aecb47a427e201f685369cb2eb94dc524358ea19 (patch) | |
| tree | eacd3ec6416844e8447ff4e11454a1ef6c6dad44 | |
| parent | b8f09e1140cfa9d34fc086ea1aa9197f3bcb0801 (diff) | |
| download | bmcweb-aecb47a427e201f685369cb2eb94dc524358ea19.tar.gz bmcweb-aecb47a427e201f685369cb2eb94dc524358ea19.zip | |
Redfish privileges
Redfish privilege authorization subsystem controlled by the
privilege_registy.json configuration file.
PropertyOverrides, SubordinateOverrides and ResourceURIOverrides
are not yet implemented.
Change-Id: I4d5670d557f4da172460ada3512e015830dab667
Signed-off-by: Borawski.Lukasz <lukasz.borawski@intel.com>
Signed-off-by: Ed Tanous <ed.tanous@intel.com>
| -rw-r--r-- | CMakeLists.txt | 4 | ||||
| -rw-r--r-- | redfish-core/include/node.hpp | 71 | ||||
| -rw-r--r-- | redfish-core/include/privileges.hpp | 223 | ||||
| -rw-r--r-- | redfish-core/include/redfish.hpp | 3 | ||||
| -rw-r--r-- | redfish-core/lib/redfish_sessions.hpp | 6 | ||||
| -rw-r--r-- | redfish-core/lib/service_root.hpp | 4 | ||||
| -rw-r--r-- | redfish-core/privilege_registry.json | 4117 | ||||
| -rw-r--r-- | redfish-core/src/privileges.cpp | 202 | ||||
| -rw-r--r-- | redfish-core/ut/privileges_test.cpp | 526 | ||||
| -rw-r--r-- | src/crow_test.cpp | 2 |
10 files changed, 5092 insertions, 66 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index c017fe1..c68c53f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,6 +125,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/redfish-core/include) set(SRC_FILES + redfish-core/src/privileges.cpp ${GENERATED_SRC_FILES} ) @@ -135,6 +136,7 @@ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/generated) # Unit Tests if(${BMCWEB_BUILD_UT}) set(UT_FILES + redfish-core/ut/privileges_test.cpp src/crow_test.cpp src/gtest_main.cpp src/token_authorization_middleware_test.cpp @@ -175,6 +177,8 @@ if(${BMCWEB_BUILD_UT}) endif(${BMCWEB_BUILD_UT}) install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/static/ DESTINATION share/www) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/redfish-core/privilege_registry.json + DESTINATION /etc/redfish.conf.d/) # bmcweb add_executable(bmcweb ${WEBSERVER_MAIN} ${HDR_FILES} ${SRC_FILES}) diff --git a/redfish-core/include/node.hpp b/redfish-core/include/node.hpp index 70b8522..6a58cb2 100644 --- a/redfish-core/include/node.hpp +++ b/redfish-core/include/node.hpp @@ -28,13 +28,12 @@ namespace redfish { class Node { public: template <typename CrowApp, typename... Params> - Node(CrowApp& app, PrivilegeProvider& provider, std::string odataType, - std::string odataId, Params... params) - : odataType(odataType), odataId(odataId) { - // privileges for the node as defined in the privileges_registry.json - entityPrivileges = provider.getPrivileges(odataId, odataType); - - app.route_dynamic(std::move(odataId)) + Node(CrowApp& app, const PrivilegeProvider& privilegeProvider, + const std::string& entityType, const std::string& entityUrl, + Params... params) + : entityPrivileges(privilegeProvider.getPrivilegesRequiredByEntity( + entityUrl, entityType)) { + app.route_dynamic(entityUrl.c_str()) .methods("GET"_method, "PATCH"_method, "POST"_method, "DELETE"_method)([&](const crow::request& req, crow::response& res, Params... params) { @@ -43,15 +42,41 @@ class Node { }); } + virtual ~Node() = default; + + protected: + // Node is designed to be an abstract class, so doGet is pure virtual + virtual void doGet(crow::response& res, const crow::request& req, + const std::vector<std::string>& params) = 0; + + virtual void doPatch(crow::response& res, const crow::request& req, + const std::vector<std::string>& params) { + res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); + res.end(); + } + + virtual void doPost(crow::response& res, const crow::request& req, + const std::vector<std::string>& params) { + res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); + res.end(); + } + + virtual void doDelete(crow::response& res, const crow::request& req, + const std::vector<std::string>& params) { + res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); + res.end(); + } + + private: template <typename CrowApp> void dispatchRequest(CrowApp& app, const crow::request& req, crow::response& res, const std::vector<std::string>& params) { - // drop requests without required privileges auto ctx = app.template get_context<crow::TokenAuthorization::Middleware>(req); - if (!entityPrivileges.isMethodAllowed(req.method, ctx.session->username)) { + if (!entityPrivileges.isMethodAllowedForUser(req.method, + ctx.session->username)) { res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); res.end(); return; @@ -81,33 +106,7 @@ class Node { return; } - protected: - const std::string odataType; - const std::string odataId; - - // Node is designed to be an abstract class, so doGet is pure virutal - virtual void doGet(crow::response& res, const crow::request& req, - const std::vector<std::string>& params) = 0; - - virtual void doPatch(crow::response& res, const crow::request& req, - const std::vector<std::string>& params) { - res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); - res.end(); - } - - virtual void doPost(crow::response& res, const crow::request& req, - const std::vector<std::string>& params) { - res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); - res.end(); - } - - virtual void doDelete(crow::response& res, const crow::request& req, - const std::vector<std::string>& params) { - res.code = static_cast<int>(HttpRespCode::METHOD_NOT_ALLOWED); - res.end(); - } - - EntityPrivileges entityPrivileges; + const EntityPrivileges entityPrivileges; }; template <typename CrowApp> diff --git a/redfish-core/include/privileges.hpp b/redfish-core/include/privileges.hpp index 290c0eb..2441104 100644 --- a/redfish-core/include/privileges.hpp +++ b/redfish-core/include/privileges.hpp @@ -15,51 +15,228 @@ */ #pragma once +#include <bitset> +#include <cstdint> +#include "crow.h" +#include <boost/container/flat_map.hpp> +#include <boost/optional.hpp> + namespace redfish { +class PrivilegeProvider; + +enum class PrivilegeType { BASE, OEM }; + +/** @brief Max number of privileges per type */ +constexpr const size_t MAX_PRIVILEGE_COUNT = 32; +using privilegeBitset = std::bitset<MAX_PRIVILEGE_COUNT>; + /** - * @brief Class used to store privileges for a given user. + * @brief Redfish privileges + * + * Entity privileges and user privileges are represented by this class. + * + * Each incoming connection requires a comparison between privileges held + * by the user issuing a request and the target entity's privileges. + * + * To ensure best runtime performance of this comparison, privileges + * are represented as bitsets. Each bit in the bitset corresponds to a + * unique privilege name. + * + * Privilege names are read from the privilege_registry.json file and + * stored in flat maps. + * + * A bit is set if the privilege is required (entity domain) or granted + * (user domain) and false otherwise. + * + * Bitset index to privilege name mapping depends on the order in which + * privileges are defined in PrivilegesUsed and OEMPrivilegesUsed arrays + * in the privilege_registry.json. */ -class UserPrivileges { - // TODO: Temporary stub, implementation will come with next patch-sets +class Privileges { + public: + /** + * @brief Retrieves the base privileges bitset + * + * @return Bitset representation of base Redfish privileges + */ + privilegeBitset getBasePrivilegeBitset() const { return basePrivilegeBitset; } + + /** + * @brief Retrieves the OEM privileges bitset + * + * @return Bitset representation of OEM Redfish privileges + */ + privilegeBitset getOEMPrivilegeBitset() const { return oemPrivilegeBitset; } + + /** + * @brief Sets given privilege in the bitset + * + * @param[in] privilege Privilege to be set + * + * @return None + */ + void setSinglePrivilege(const std::string& privilege) { + auto index = getBitsetIndexForPrivilege(privilege, PrivilegeType::BASE); + if (index) { + basePrivilegeBitset.set(*index); + return; + } + + index = getBitsetIndexForPrivilege(privilege, PrivilegeType::OEM); + if (index) { + oemPrivilegeBitset.set(*index); + } + } + + /** + * @brief Retrieves names of all active privileges for a given type + * + * @param[in] type Base or OEM + * + * @return Vector of active privileges + */ + std::vector<std::string> getActivePrivilegeNames( + const PrivilegeType type) const { + std::vector<std::string> activePrivileges; + + if (type == PrivilegeType::BASE) { + for (const auto& pair : basePrivNameToIndexMap) { + if (basePrivilegeBitset.test(pair.second)) { + activePrivileges.emplace_back(pair.first); + } + } + } else { + for (const auto& pair : oemPrivNameToIndexMap) { + if (oemPrivilegeBitset.test(pair.second)) { + activePrivileges.emplace_back(pair.first); + } + } + } + + return activePrivileges; + } + private: - uint32_t redfishPrivileges; - uint32_t oemPrivileges; + boost::optional<size_t> getBitsetIndexForPrivilege( + const std::string& privilege, const PrivilegeType type) const { + if (type == PrivilegeType::BASE) { + const auto pair = basePrivNameToIndexMap.find(privilege); + if (pair != basePrivNameToIndexMap.end()) { + return pair->second; + } + } else { + const auto pair = oemPrivNameToIndexMap.find(privilege); + if (pair != oemPrivNameToIndexMap.end()) { + return pair->second; + } + } + + return boost::none; + } + + privilegeBitset basePrivilegeBitset; + privilegeBitset oemPrivilegeBitset; + + static boost::container::flat_map<std::string, size_t> basePrivNameToIndexMap; + static boost::container::flat_map<std::string, size_t> oemPrivNameToIndexMap; + + friend class PrivilegeProvider; }; /** - * @brief Class used to store privileges for a given Redfish entity. + * @brief Class used to store privileges for Redfish entities */ class EntityPrivileges { - // TODO: Temporary stub, implementation will come with next patch-sets public: - bool isMethodAllowed(const crow::HTTPMethod& method, - const std::string& username) const { - return true; + /** + * @brief Checks if a user is allowed to call an HTTP method + * + * @param[in] method HTTP method + * @param[in] user Username + * + * @return True if method allowed, false otherwise + */ + bool isMethodAllowedForUser(const crow::HTTPMethod method, + const std::string& user) const; + + /** + * @brief Checks if given privileges allow to call an HTTP method + * + * @param[in] method HTTP method + * @param[in] user Privileges + * + * @return True if method allowed, false otherwise + */ + bool isMethodAllowedWithPrivileges(const crow::HTTPMethod method, + const Privileges& userPrivileges) const; + + /** + * @brief Sets required privileges for a method on a given entity + * + * @param[in] method HTTP method + * @param[in] privileges Required privileges + * + * @return None + */ + void addPrivilegesRequiredByMethod(const crow::HTTPMethod method, + const Privileges& privileges) { + methodToPrivilegeMap[method].push_back(privileges); } + + private: + bool verifyPrivileges(const privilegeBitset userPrivilegeBitset, + const privilegeBitset requiredPrivilegeBitset) const; + + boost::container::flat_map<crow::HTTPMethod, std::vector<Privileges>> + methodToPrivilegeMap; }; /** * @brief Class used to: - * - read the PrivilegeRegistry file, - * - provide EntityPrivileges objects to callers. + * - read the privilege_registry.json file + * - provide EntityPrivileges objects to callers * - * To save runtime memory object of this class should - * exist only for the time required to install all Nodes. + * To save runtime memory, object of this class should + * exist only for the time required to install all Nodes */ class PrivilegeProvider { - // TODO: Temporary stub, implementation will come with next patch-sets public: - PrivilegeProvider() { - // load privilege_registry.json to memory - } + PrivilegeProvider(const std::string& privilegeRegistryPath) { + // TODO: read this path from the configuration once its available + std::ifstream privilegeRegistryFile{privilegeRegistryPath}; - EntityPrivileges getPrivileges(const std::string& entity_url, - const std::string& entity_type) const { - // return an entity privilege object based on the privilege_registry.json, - // currently returning default constructed object - return EntityPrivileges(); + if (privilegeRegistryFile.is_open()) { + if (!loadPrivilegesFromFile(privilegeRegistryFile)) { + privilegeRegistryJson.clear(); + CROW_LOG_ERROR << "Couldn't parse privilege_registry.json"; + } + } else { + CROW_LOG_ERROR << "Couldn't open privilege_registry.json"; + } } + + /** + * @brief Gets required privileges for a certain entity type + * + * @param[in] entityUrl Entity url + * @param[in] entityType Entity type + * + * @return EntityPrivilege object + */ + EntityPrivileges getPrivilegesRequiredByEntity( + const std::string& entityUrl, const std::string& entityType) const; + + private: + bool loadPrivilegesFromFile(std::ifstream& privilegeRegistryFile); + bool privilegeRegistryHasRequiredFields() const; + bool parseOperationMap(const nlohmann::json& operationMap, + EntityPrivileges& entityPrivileges) const; + bool fillPrivilegeMap(const nlohmann::json& privilegesUsed, + boost::container::flat_map<std::string, size_t>& + privilegeToIndexMap) const; + + nlohmann::json privilegeRegistryJson; }; } // namespace redfish diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp index 0598636..b67c857 100644 --- a/redfish-core/include/redfish.hpp +++ b/redfish-core/include/redfish.hpp @@ -34,7 +34,8 @@ class RedfishService { */ template <typename CrowApp> RedfishService(CrowApp& app) { - auto privilegeProvider = PrivilegeProvider(); + auto privilegeProvider = + PrivilegeProvider("/etc/redfish.conf.d/privilege_registry.json"); nodes.emplace_back( std::make_unique<SessionCollection>(app, privilegeProvider)); diff --git a/redfish-core/lib/redfish_sessions.hpp b/redfish-core/lib/redfish_sessions.hpp index 0835fa1..11cde72 100644 --- a/redfish-core/lib/redfish_sessions.hpp +++ b/redfish-core/lib/redfish_sessions.hpp @@ -28,7 +28,7 @@ class Sessions : public Node { Sessions(CrowApp& app, PrivilegeProvider& provider) : Node(app, provider, "#Session.v1_0_2.Session", "/redfish/v1/SessionService/Sessions/<str>", std::string()) { - nodeJson["@odata.type"] = Node::odataType; + nodeJson["@odata.type"] = "#Session.v1_0_2.Session"; nodeJson["@odata.context"] = "/redfish/v1/$metadata#Session.Session"; nodeJson["Name"] = "User Session"; nodeJson["Description"] = "Manager User Session"; @@ -95,8 +95,8 @@ class SessionCollection : public Node { : Node(app, provider, "#SessionCollection.SessionCollection", "/redfish/v1/SessionService/Sessions/"), memberSession(app, provider) { - nodeJson["@odata.type"] = Node::odataType; - nodeJson["@odata.id"] = Node::odataId; + nodeJson["@odata.type"] = "#SessionCollection.SessionCollection"; + nodeJson["@odata.id"] = "/redfish/v1/SessionService/Sessions/"; nodeJson["@odata.context"] = "/redfish/v1/$metadata#SessionCollection.SessionCollection"; nodeJson["Name"] = "Session Collection"; diff --git a/redfish-core/lib/service_root.hpp b/redfish-core/lib/service_root.hpp index 55015e4..cdb0000 100644 --- a/redfish-core/lib/service_root.hpp +++ b/redfish-core/lib/service_root.hpp @@ -24,8 +24,8 @@ class ServiceRoot : public Node { template <typename CrowApp, typename PrivilegeProvider> ServiceRoot(CrowApp& app, PrivilegeProvider& provider) : Node(app, provider, "#ServiceRoot.v1_1_1.ServiceRoot", "/redfish/v1/") { - nodeJson["@odata.type"] = Node::odataType; - nodeJson["@odata.id"] = Node::odataId; + nodeJson["@odata.type"] = "#ServiceRoot.v1_1_1.ServiceRoot"; + nodeJson["@odata.id"] = "/redfish/v1"; nodeJson["@odata.context"] = "/redfish/v1/$metadata#ServiceRoot.ServiceRoot"; nodeJson["Id"] = "RootService"; diff --git a/redfish-core/privilege_registry.json b/redfish-core/privilege_registry.json new file mode 100644 index 0000000..cfd5cdd --- /dev/null +++ b/redfish-core/privilege_registry.json @@ -0,0 +1,4117 @@ +{
+ "@Redfish.Copyright": "Copyright 2015-2017 Distributed Management Task Force, Inc. (DMTF). All rights reserved.",
+ "@odata.type": "#PrivilegeRegistry.v1_0_0.PrivilegeRegistry",
+ "Id": "Redfish_1.0.2_PrivilegeRegistry",
+ "Name": "Privilege Mapping array collection",
+ "PrivilegesUsed": [
+ "Login",
+ "ConfigureManager",
+ "ConfigureUsers",
+ "ConfigureComponents",
+ "ConfigureSelf"
+ ],
+ "OEMPrivilegesUsed": [
+ "OEMRoot"
+ ],
+ "Mappings": [
+ {
+ "Entity": "Manager",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ManagerCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ComputerSystem",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ComputerSystemCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "EthernetInterface",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "SubordinateOverrides": [
+ {
+ "Targets": [
+ "Manager",
+ "EthernetInterfaceCollection"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "EthernetInterfaceCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ManagerAccount",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ },
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ },
+ {
+ "Privilege": [
+ "ConfigureSelf"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ]
+ },
+ "PropertyOverrides": [
+ {
+ "Targets": [
+ "Password"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ },
+ {
+ "Privilege": [
+ "ConfigureSelf"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "Entity": "ManagerAccountCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ },
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "AccountService",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ },
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureUsers"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Chassis",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ChassisCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "LogService",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "SubordinateOverrides": [
+ {
+ "Targets": [
+ "ComputerSystem",
+ "LogServiceCollection"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Targets": [
+ "Chassis",
+ "LogServiceCollection"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "LogServiceCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "SubordinateOverrides": [
+ {
+ "Targets": [
+ "ComputerSystem"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Targets": [
+ "Chassis"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "LogEntry",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "SubordinateOverrides": [
+ {
+ "Targets": [
+ "ComputerSystem",
+ "LogServiceCollection",
+ "LogService",
+ "LogEntryCollection"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Targets": [
+ "Chassis",
+ "LogServiceCollection",
+ "LogService",
+ "LogEntryCollection"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "LogEntryCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "SubordinateOverrides": [
+ {
+ "Targets": [
+ "ComputerSystem",
+ "LogServiceCollection",
+ "LogService"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Targets": [
+ "Chassis",
+ "LogServiceCollection",
+ "LogService"
+ ],
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Power",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Processor",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ProcessorCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Role",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "RoleCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SerialInterface",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SerialInterfaceCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SessionService",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Session",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SessionCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": []
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Task",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "TaskCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "TaskService",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Thermal",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "VirtualMedia",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "VirtualMediaCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "VLanNetworkInterface",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "VLanNetworkInterfaceCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "BIOS",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Drive",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "EventService",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "EventDestination",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "EventDestinationCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Fabric",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "FabricCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ManagerNetworkProtocol",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Memory",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MemoryCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MemoryChunks",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MemoryChunksCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MemoryDomain",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MemoryDomainCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MemoryMetrics",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "PCIeDevice",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "PCIeFunction",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Port",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "PortCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SecureBoot",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SoftwareInventory",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SoftwareInventoryCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Storage",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "StorageCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Switch",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SwitchCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "UpdateService",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Volume",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "VolumeCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Zone",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ZoneCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Endpoint",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "EndpointCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "JSONSchemaFile",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "JSONSchemaFileCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MessageRegistry",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MessageRegistryCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MessageRegistryFile",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "MessageRegistryFileCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "PhysicalContext",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "Redundancy",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "ServiceRoot",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": []
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureManager"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SimpleStorage",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ },
+ {
+ "Entity": "SimpleStorageCollection",
+ "OperationMap": {
+ "GET": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "HEAD": [
+ {
+ "Privilege": [
+ "Login"
+ ]
+ }
+ ],
+ "PATCH": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "POST": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "PUT": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ],
+ "DELETE": [
+ {
+ "Privilege": [
+ "ConfigureComponents"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+}
diff --git a/redfish-core/src/privileges.cpp b/redfish-core/src/privileges.cpp new file mode 100644 index 0000000..5fbce23 --- /dev/null +++ b/redfish-core/src/privileges.cpp @@ -0,0 +1,202 @@ +/* +// Copyright (c) 2018 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ +#include "privileges.hpp" + +namespace redfish { + +boost::container::flat_map<std::string, size_t> + Privileges::basePrivNameToIndexMap; +boost::container::flat_map<std::string, size_t> + Privileges::oemPrivNameToIndexMap; + +bool EntityPrivileges::isMethodAllowedForUser(const crow::HTTPMethod method, + const std::string& user) const { + // TODO: load user privileges from configuration as soon as its available + // now we are granting only Login. + auto userPrivileges = Privileges(); + userPrivileges.setSinglePrivilege("Login"); + + return isMethodAllowedWithPrivileges(method, userPrivileges); +} + +bool EntityPrivileges::isMethodAllowedWithPrivileges( + const crow::HTTPMethod method, const Privileges& userPrivileges) const { + if (methodToPrivilegeMap.find(method) == methodToPrivilegeMap.end()) { + return false; + } + + for (auto& requiredPrivileges : methodToPrivilegeMap.at(method)) { + // Check if user has required base privileges + if (!verifyPrivileges(userPrivileges.getBasePrivilegeBitset(), + requiredPrivileges.getBasePrivilegeBitset())) { + continue; + } + + // Check if user has required OEM privileges + if (!verifyPrivileges(userPrivileges.getOEMPrivilegeBitset(), + requiredPrivileges.getOEMPrivilegeBitset())) { + continue; + } + + return true; + } + return false; +} + +bool EntityPrivileges::verifyPrivileges( + const privilegeBitset userPrivilegeBitset, + const privilegeBitset requiredPrivilegeBitset) const { + return (userPrivilegeBitset & requiredPrivilegeBitset) == + requiredPrivilegeBitset; +} + +EntityPrivileges PrivilegeProvider::getPrivilegesRequiredByEntity( + const std::string& entityUrl, const std::string& entityType) const { + if (privilegeRegistryJson.empty()) { + return EntityPrivileges(); + } + + // type from @odata.type e.g: ServiceRoot from #ServiceRoot.v1_1_1.ServiceRoot + auto entity = entityType.substr(entityType.find_last_of(".") + strlen(".")); + + for (auto mapping : privilegeRegistryJson.at("Mappings")) { + const auto& entityJson = mapping.find("Entity"); + const auto& operationMapJson = mapping.find("OperationMap"); + const auto& propertyOverridesJson = mapping.find("PropertyOverrides"); + const auto& subordinateOverridesJson = mapping.find("SubordinateOverrides"); + const auto& resourceURIOverridesJson = mapping.find("ResourceURIOverrides"); + + if (entityJson == mapping.end() || operationMapJson == mapping.end()) { + return EntityPrivileges(); + } + + if (entityJson->is_string() && entity == entityJson.value()) { + auto entityPrivileges = EntityPrivileges(); + + if (!parseOperationMap(operationMapJson.value(), entityPrivileges)) { + return EntityPrivileges(); + } + + if (propertyOverridesJson != mapping.end()) { + // TODO: implementation comes in next patch-sets + } + if (subordinateOverridesJson != mapping.end()) { + // TODO: implementation comes in next patch-sets + } + if (resourceURIOverridesJson != mapping.end()) { + // TODO: implementation comes in next patch-sets + } + + return entityPrivileges; + } + } + return EntityPrivileges(); +} + +bool PrivilegeProvider::parseOperationMap( + const nlohmann::json& operationMap, + EntityPrivileges& entityPrivileges) const { + for (auto it = operationMap.begin(); it != operationMap.end(); ++it) { + const std::string& method = it.key(); + const nlohmann::json& privilegesForMethod = it.value(); + + for (const auto& privilegeOr : privilegesForMethod) { + const auto& privilegeJson = privilegeOr.find("Privilege"); + + if (privilegeJson == privilegeOr.end()) { + return false; + } + auto privileges = Privileges(); + + for (auto& privilegeAnd : privilegeJson.value()) { + if (!privilegeAnd.is_string()) { + return false; + } + privileges.setSinglePrivilege(privilegeAnd); + } + entityPrivileges.addPrivilegesRequiredByMethod(operator"" _method( + method.c_str(), + method.size()), + privileges); + } + } + return true; +} + +bool PrivilegeProvider::loadPrivilegesFromFile( + std::ifstream& privilegeRegistryFile) { + privilegeRegistryJson = + nlohmann::json::parse(privilegeRegistryFile, nullptr, false); + + if (!privilegeRegistryHasRequiredFields()) { + return false; + } + + const nlohmann::json& basePrivilegesUsed = + privilegeRegistryJson.at("PrivilegesUsed"); + if (basePrivilegesUsed.size() == 0) { + return false; + } + if (!fillPrivilegeMap(basePrivilegesUsed, + Privileges::basePrivNameToIndexMap)) { + return false; + } + + const nlohmann::json& oemPrivilegesUsed = + privilegeRegistryJson.at("OEMPrivilegesUsed"); + if (!fillPrivilegeMap(oemPrivilegesUsed, Privileges::oemPrivNameToIndexMap)) { + return false; + } + + return true; +} + +bool PrivilegeProvider::privilegeRegistryHasRequiredFields() const { + if (privilegeRegistryJson.is_discarded() || + privilegeRegistryJson.find("@Redfish.Copyright") == + privilegeRegistryJson.end() || + privilegeRegistryJson.find("@odata.type") == + privilegeRegistryJson.end() || + privilegeRegistryJson.find("Id") == privilegeRegistryJson.end() || + privilegeRegistryJson.find("Name") == privilegeRegistryJson.end() || + privilegeRegistryJson.find("Mappings") == privilegeRegistryJson.end() || + privilegeRegistryJson.find("PrivilegesUsed") == + privilegeRegistryJson.end() || + privilegeRegistryJson.find("OEMPrivilegesUsed") == + privilegeRegistryJson.end()) { + return false; + } + return true; +} + +bool PrivilegeProvider::fillPrivilegeMap( + const nlohmann::json& privilegesUsed, + boost::container::flat_map<std::string, size_t>& privilegeToIndexMap) + const { + privilegeToIndexMap.clear(); + for (auto& privilege : privilegesUsed) { + if (privilegeToIndexMap.size() < MAX_PRIVILEGE_COUNT) { + if (!privilege.is_string()) { + return false; + } + privilegeToIndexMap.insert(std::pair<std::string, size_t>( + privilege.get<std::string>(), privilegeToIndexMap.size())); + } + } + return true; +} + +} // namespace redfish diff --git a/redfish-core/ut/privileges_test.cpp b/redfish-core/ut/privileges_test.cpp new file mode 100644 index 0000000..9d0d156 --- /dev/null +++ b/redfish-core/ut/privileges_test.cpp @@ -0,0 +1,526 @@ +#include "privileges.hpp" +#include <fstream> +#include <string> +#include "nlohmann/json.hpp" +#include "gmock/gmock.h" + +using namespace redfish; + +class PrivilegeTest : public testing::Test { + protected: + nlohmann::json privilegeRegistryMockJson; + + std::vector<std::string> expectedBasePrivileges{ + "Login", "ConfigureManager", "ConfigureUsers", "ConfigureComponents", + "ConfigureSelf"}; + + std::vector<std::string> expectedOEMPrivileges{"OEMRoot", "OEMDummy"}; + + PrivilegeTest() { + crow::logger::setLogLevel(crow::LogLevel::CRITICAL); + + std::ofstream privilegeRegistryMockOfstream("privilege_registry_mock.json"); + privilegeRegistryMockJson = nlohmann::json::parse( + "{\ + \"@Redfish.Copyright\": \"Dummy copyright\",\ + \"@odata.type\": \"#PrivilegeRegistry.v1_0_0.PrivilegeRegistry\",\ + \"Id\": \"Dummy id\",\ + \"Name\": \"Dummy name\",\ + \"PrivilegesUsed\": [\ + \"Login\",\ + \"ConfigureManager\",\ + \"ConfigureUsers\",\ + \"ConfigureComponents\",\ + \"ConfigureSelf\"],\ + \"OEMPrivilegesUsed\": [\ + \"OEMRoot\",\ + \"OEMDummy\"],\ + \"Mappings\": [\ + {\ + \"Entity\": \"TestEntity\",\ + \"OperationMap\": {\ + \"GET\": [\ + {\ + \"Privilege\": [\ + \"Login\"\ + ]\ + }\ + ],\ + \"PATCH\": [\ + {\ + \"Privilege\": [\ + \"ConfigureManager\"\ + ]\ + },\ + {\ + \"Privilege\": [\ + \"ConfigureUser\",\ + \"ConfigureDummy\",\ + \"OEMRoot\"\ + ]\ + }\ + ],\ + \"POST\": [\ + {\ + \"Privilege\": [\ + \"ConfigureManager\",\ + \"OEMDummy\"\ + ]\ + }\ + ],\ + \"DELETE\": [\ + {\ + \"Privilege\": [\ + \"ConfigureManager\"\ + ]\ + }\ + ]\ + }\ + },\ + {\ + \"Entity\": \"EntityWithNonStringPrivilege\",\ + \"OperationMap\": {\ + \"GET\": [\ + {\ + \"Privilege\": [\"Login\"]\ + }\ + ],\ + \"POST\": [\ + {\ + \"Privilege\": [1]\ + }\ + ]\ + }\ + }\ + ]\ + }"); + privilegeRegistryMockOfstream << std::setw(4) << privilegeRegistryMockJson + << std::endl; + privilegeRegistryMockOfstream.close(); + } + + virtual ~PrivilegeTest() { std::remove("privilege_registry_mock.json"); } + + void removeFieldFromRegistry(const std::string& field) { + std::ifstream in("privilege_registry_mock.json"); + nlohmann::json tempJson = nlohmann::json::parse(in); + in.close(); + + tempJson.erase(field); + + std::ofstream out("privilege_registry_mock.json"); + out << std::setw(4) << tempJson << std::endl; + out.close(); + } + + void removeFieldFromMappings(const std::string& field) { + std::ifstream in("privilege_registry_mock.json"); + nlohmann::json tempJson = nlohmann::json::parse(in); + in.close(); + + tempJson.at("Mappings")[0].erase(field); + + std::ofstream out("privilege_registry_mock.json"); + out << std::setw(4) << tempJson << std::endl; + out.close(); + } + + void clearArryInJson(const std::string& key) { + std::ifstream in("privilege_registry_mock.json"); + nlohmann::json tempJson = nlohmann::json::parse(in); + in.close(); + + tempJson[key].clear(); + + std::ofstream out("privilege_registry_mock.json"); + out << std::setw(4) << tempJson << std::endl; + out.close(); + } + + template <typename T> + void fillPrivilegeArray(const std::string& key, + const std::vector<T>& values) { + std::ifstream in("privilege_registry_mock.json"); + nlohmann::json tempJson = nlohmann::json::parse(in); + in.close(); + + tempJson[key].clear(); + for (const auto& value : values) { + tempJson[key].push_back(value); + } + + std::ofstream out("privilege_registry_mock.json"); + out << std::setw(4) << tempJson << std::endl; + out.close(); + } + + template <typename T> + void addRequiredPrivilege(const T& value) { + std::ifstream in("privilege_registry_mock.json"); + nlohmann::json tempJson = nlohmann::json::parse(in); + in.close(); + + tempJson["Mappings"][0]["OperationMap"]["GET"][0]["Privilege"].push_back( + value); + + std::ofstream out("privilege_registry_mock.json"); + out << std::setw(4) << tempJson << std::endl; + out.close(); + } + + bool isPrivilegeRegistryParsed(const EntityPrivileges& entityPrivileges) { + auto userPrivileges = Privileges(); + userPrivileges.setSinglePrivilege("Login"); + // given the privileges_registry_mock.json, GET should be allowed with Login + // if the file got parsed successfully + return entityPrivileges.isMethodAllowedWithPrivileges(crow::HTTPMethod::GET, + userPrivileges); + } +}; + +TEST_F(PrivilegeTest, PrivilegeRegistryJsonSuccessfullParse) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_TRUE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryJsonNotFound) { + std::remove("privilege_registry_mock.json"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingCopyright) { + removeFieldFromRegistry("@Redfish.Copyright"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingOdataType) { + removeFieldFromRegistry("@odata.type"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingId) { + removeFieldFromRegistry("Id"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingName) { + removeFieldFromRegistry("Name"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingMappings) { + removeFieldFromRegistry("Mappings"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingPrivilegesUsed) { + removeFieldFromRegistry("PrivilegesUsed"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingOEMPrivilegesUsed) { + removeFieldFromRegistry("OEMPrivilegesUsed"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryMissingOperationMap) { + removeFieldFromMappings("OperationMap"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryPrivilegesUsedMayNotBeEmpty) { + clearArryInJson("PrivilegesUsed"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeRegistryOEMPrivilegesUsedMayByEmpty) { + clearArryInJson("OEMPrivilegesUsed"); + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_TRUE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeValuesMayOnlyBeStrings) { + std::vector<int> privilegesUsed = {1, 3, 4}; + fillPrivilegeArray("PrivilegesUsed", privilegesUsed); + + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, OnlyMaxNoOfBasePrivilegesGetsLoaded) { + const std::string excessivePrivilege("ExcessivePrivilege"); + std::vector<std::string> privilegesUsed; + + for (int i = 0; i < MAX_PRIVILEGE_COUNT; i++) { + privilegesUsed.push_back(std::to_string(i)); + } + privilegesUsed.push_back(excessivePrivilege); + + fillPrivilegeArray("PrivilegesUsed", privilegesUsed); + addRequiredPrivilege(excessivePrivilege); + + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + Privileges privileges; + privileges.setSinglePrivilege(excessivePrivilege); + + EXPECT_EQ(privileges.getBasePrivilegeBitset(), 0); +} + +TEST_F(PrivilegeTest, OnlyMaxNoOfOEMPrivilegesGetsLoaded) { + const std::string excessivePrivilege("ExcessivePrivilege"); + std::vector<std::string> privilegesUsed; + + for (int i = 0; i < MAX_PRIVILEGE_COUNT; i++) { + privilegesUsed.push_back(std::to_string(i)); + } + privilegesUsed.push_back(excessivePrivilege); + + fillPrivilegeArray("OEMPrivilegesUsed", privilegesUsed); + addRequiredPrivilege(excessivePrivilege); + + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + Privileges privileges; + privileges.setSinglePrivilege(excessivePrivilege); + + EXPECT_EQ(privileges.getOEMPrivilegeBitset(), 0); +} + +TEST_F(PrivilegeTest, LoadEntityPrivilegesForExistingEntity) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.TestEntity"); + EXPECT_TRUE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, LoadEntityPrivilegesForNonExistingEntity) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = + privilegeProvider.getPrivilegesRequiredByEntity("", "foo.bar.NotExists"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, LoadEntityPrivilegesForEntityWithNonStringPrivilege) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + auto entityPrivileges = privilegeProvider.getPrivilegesRequiredByEntity( + "", "foo.bar.EntityWithNonStringPrivilege"); + EXPECT_FALSE(isPrivilegeRegistryParsed(entityPrivileges)); +} + +TEST_F(PrivilegeTest, DefaultEntityPrivilegesDenyAccess) { + auto entityPrivileges = EntityPrivileges(); + + auto res = + entityPrivileges.isMethodAllowedForUser(crow::HTTPMethod::GET, "user"); + EXPECT_FALSE(res); +} + +TEST_F(PrivilegeTest, PrivilegeCheckForSingleCaseSuccess) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + auto entityPrivileges = EntityPrivileges(); + auto userPrivileges = Privileges(); + auto requiredPrivileges = Privileges(); + + userPrivileges.setSinglePrivilege("Login"); + requiredPrivileges.setSinglePrivilege("Login"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + EXPECT_TRUE(entityPrivileges.isMethodAllowedWithPrivileges( + crow::HTTPMethod::GET, userPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeCheckForSingleCaseFailure) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + auto entityPrivileges = EntityPrivileges(); + auto userPrivileges = Privileges(); + auto requiredPrivileges = Privileges(); + + userPrivileges.setSinglePrivilege("Login"); + requiredPrivileges.setSinglePrivilege("ConfigureManager"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + EXPECT_FALSE(entityPrivileges.isMethodAllowedWithPrivileges( + crow::HTTPMethod::GET, userPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeCheckForANDCaseSuccess) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + auto entityPrivileges = EntityPrivileges(); + auto userPrivileges = Privileges(); + auto requiredPrivileges = Privileges(); + + userPrivileges.setSinglePrivilege("Login"); + userPrivileges.setSinglePrivilege("ConfigureManager"); + userPrivileges.setSinglePrivilege("OEMRoot"); + requiredPrivileges.setSinglePrivilege("Login"); + requiredPrivileges.setSinglePrivilege("ConfigureManager"); + requiredPrivileges.setSinglePrivilege("OEMRoot"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + EXPECT_TRUE(entityPrivileges.isMethodAllowedWithPrivileges( + crow::HTTPMethod::GET, userPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeCheckForANDCaseFailure) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + auto entityPrivileges = EntityPrivileges(); + auto userPrivileges = Privileges(); + auto requiredPrivileges = Privileges(); + + userPrivileges.setSinglePrivilege("Login"); + userPrivileges.setSinglePrivilege("ConfigureUsers"); + requiredPrivileges.setSinglePrivilege("Login"); + requiredPrivileges.setSinglePrivilege("OEMDummy"); + requiredPrivileges.setSinglePrivilege("ConfigureUsers"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + EXPECT_FALSE(entityPrivileges.isMethodAllowedWithPrivileges( + crow::HTTPMethod::GET, userPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeCheckForORCaseSuccess) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + auto entityPrivileges = EntityPrivileges(); + auto userPrivileges = Privileges(); + auto requiredPrivileges = Privileges(); + + userPrivileges.setSinglePrivilege("OEMRoot"); + requiredPrivileges.setSinglePrivilege("Login"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + requiredPrivileges = Privileges(); + requiredPrivileges.setSinglePrivilege("OEMRoot"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + EXPECT_TRUE(entityPrivileges.isMethodAllowedWithPrivileges( + crow::HTTPMethod::GET, userPrivileges)); +} + +TEST_F(PrivilegeTest, PrivilegeCheckForORCaseFailure) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + auto entityPrivileges = EntityPrivileges(); + auto userPrivileges = Privileges(); + auto requiredPrivileges = Privileges(); + + userPrivileges.setSinglePrivilege("ConfigureComponents"); + requiredPrivileges.setSinglePrivilege("Login"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + requiredPrivileges = Privileges(); + requiredPrivileges.setSinglePrivilege("ConfigureManager"); + entityPrivileges.addPrivilegesRequiredByMethod(crow::HTTPMethod::GET, + requiredPrivileges); + EXPECT_FALSE(entityPrivileges.isMethodAllowedWithPrivileges( + crow::HTTPMethod::GET, userPrivileges)); +} + +TEST_F(PrivilegeTest, DefaultPrivilegeBitsetsAreEmpty) { + Privileges privileges; + EXPECT_TRUE(privileges.getBasePrivilegeBitset() == 0); + EXPECT_TRUE(privileges.getOEMPrivilegeBitset() == 0); +} + +TEST_F(PrivilegeTest, UniqueBitsAssignedForAllPrivilegeNames) { + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + Privileges privileges; + + for (const auto& privilege : expectedBasePrivileges) { + privileges.setSinglePrivilege(privilege); + } + + for (const auto& privilege : expectedOEMPrivileges) { + privileges.setSinglePrivilege(privilege); + } + + EXPECT_EQ(privileges.getBasePrivilegeBitset().count(), + expectedBasePrivileges.size()); + EXPECT_EQ(privileges.getOEMPrivilegeBitset().count(), + expectedOEMPrivileges.size()); +} + +TEST_F(PrivilegeTest, GetActiveBasePrivilegeNames) { + Privileges privileges; + + EXPECT_EQ(privileges.getActivePrivilegeNames(PrivilegeType::BASE), + std::vector<std::string>()); + + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + for (const auto& privilege : expectedBasePrivileges) { + privileges.setSinglePrivilege(privilege); + } + + std::vector<std::string> activePrivileges = + privileges.getActivePrivilegeNames(PrivilegeType::BASE); + + std::sort(expectedBasePrivileges.begin(), expectedBasePrivileges.end()); + std::sort(activePrivileges.begin(), activePrivileges.end()); + + EXPECT_EQ(activePrivileges, expectedBasePrivileges); +} + +TEST_F(PrivilegeTest, GetActiveOEMPrivilegeNames) { + Privileges privileges; + + EXPECT_EQ(privileges.getActivePrivilegeNames(PrivilegeType::OEM), + std::vector<std::string>()); + + PrivilegeProvider privilegeProvider("privilege_registry_mock.json"); + + for (const auto& privilege : expectedOEMPrivileges) { + privileges.setSinglePrivilege(privilege); + } + + std::vector<std::string> activePrivileges = + privileges.getActivePrivilegeNames(PrivilegeType::OEM); + + std::sort(expectedOEMPrivileges.begin(), expectedOEMPrivileges.end()); + std::sort(activePrivileges.begin(), activePrivileges.end()); + + EXPECT_EQ(activePrivileges, expectedOEMPrivileges); +} diff --git a/src/crow_test.cpp b/src/crow_test.cpp index e84c1a5..942095d 100644 --- a/src/crow_test.cpp +++ b/src/crow_test.cpp @@ -556,7 +556,7 @@ TEST(Crow, json_read_real) { auto ret = json::load( R"---({"balloons":[{"mode":"ellipse","left":0.036303908355795146,"right":0.18320417789757412,"top":0.05319940476190476,"bottom":0.15224702380952382,"index":"0"},{"mode":"ellipse","left":0.3296201145552561,"right":0.47921580188679247,"top":0.05873511904761905,"bottom":0.1577827380952381,"index":"1"},{"mode":"ellipse","left":0.4996841307277628,"right":0.6425412735849056,"top":0.052113095238095236,"bottom":0.12830357142857143,"index":"2"},{"mode":"ellipse","left":0.7871041105121294,"right":0.954220013477089,"top":0.05869047619047619,"bottom":0.1625,"index":"3"},{"mode":"ellipse","left":0.8144794474393531,"right":0.9721613881401617,"top":0.1399404761904762,"bottom":0.24470238095238095,"index":"4"},{"mode":"ellipse","left":0.04527459568733154,"right":0.2096950808625337,"top":0.35267857142857145,"bottom":0.42791666666666667,"index":"5"},{"mode":"ellipse","left":0.855731974393531,"right":0.9352467991913747,"top":0.3816220238095238,"bottom":0.4282886904761905,"index":"6"},{"mode":"ellipse","left":0.39414167789757415,"right":0.5316079851752021,"top":0.3809375,"bottom":0.4571279761904762,"index":"7"},{"mode":"ellipse","left":0.03522995283018868,"right":0.1915641846361186,"top":0.6164136904761904,"bottom":0.7192708333333333,"index":"8"},{"mode":"ellipse","left":0.05675117924528302,"right":0.21308541105121293,"top":0.7045386904761904,"bottom":0.8016815476190476,"index":"9"}]})---"); - ASSERT_TRUE(ret); + ASSERT_TRUE(static_cast<bool>(ret)); } TEST(Crow, json_read_unescaping) { |

