blob: 1793a5046a8fd0901b5b30acf5e029175d589325 [file] [log] [blame]
Borawski.Lukasz86e1b662018-01-19 14:22:14 +01001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16#pragma once
17
zhanghch058d1b46d2021-04-01 11:18:24 +080018#include "async_resp.hpp"
Ed Tanous04e438c2020-10-03 08:06:26 -070019#include "http_request.hpp"
20#include "http_response.hpp"
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010021#include "privileges.hpp"
Ed Tanousa8c4ce92021-03-24 08:44:51 -070022#include "redfish_v1.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070023
Ed Tanousa0803ef2018-08-29 13:29:23 -070024#include <error_messages.hpp>
Ed Tanousa8c4ce92021-03-24 08:44:51 -070025#include <rf_async_resp.hpp>
Ed Tanousa0803ef2018-08-29 13:29:23 -070026
Gunnar Mills1214b7e2020-06-04 10:11:30 -050027#include <vector>
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010028
Ed Tanous1abe55e2018-09-05 08:30:59 -070029namespace redfish
30{
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010031
32/**
33 * @brief Abstract class used for implementing Redfish nodes.
34 *
35 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070036class Node
37{
Ed Tanous4df1bee2021-03-24 08:23:03 -070038 private:
zhanghch058d1b46d2021-04-01 11:18:24 +080039 bool redfishPreChecks(const crow::Request& req,
40 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
Ed Tanous4df1bee2021-03-24 08:23:03 -070041 {
42 std::string_view odataHeader = req.getHeaderValue("OData-Version");
43 if (odataHeader.empty())
44 {
45 // Clients aren't required to provide odata version
46 return true;
47 }
48 if (odataHeader != "4.0")
49 {
zhanghch058d1b46d2021-04-01 11:18:24 +080050 redfish::messages::preconditionFailed(asyncResp->res);
Ed Tanous4df1bee2021-03-24 08:23:03 -070051 return false;
52 }
53
zhanghch058d1b46d2021-04-01 11:18:24 +080054 asyncResp->res.addHeader("OData-Version", "4.0");
Ed Tanous4df1bee2021-03-24 08:23:03 -070055 return true;
56 }
57
Ed Tanous1abe55e2018-09-05 08:30:59 -070058 public:
59 template <typename... Params>
zhanghch058d1b46d2021-04-01 11:18:24 +080060 Node(App& app, std::string&& entityUrl,
61 [[maybe_unused]] Params... paramsIn) :
62 app(app)
Ed Tanous1abe55e2018-09-05 08:30:59 -070063 {
Tanousf00032d2018-11-05 01:18:10 -030064 crow::DynamicRule& get = app.routeDynamic(entityUrl.c_str());
65 getRule = &get;
Ed Tanousb41187f2019-10-24 16:30:02 -070066 get.methods(boost::beast::http::verb::get)(
zhanghch058d1b46d2021-04-01 11:18:24 +080067 [this](const crow::Request& req,
68 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousb41187f2019-10-24 16:30:02 -070069 Params... params) {
zhanghch058d1b46d2021-04-01 11:18:24 +080070 if (!redfishPreChecks(req, asyncResp))
Ed Tanous4df1bee2021-03-24 08:23:03 -070071 {
72 return;
73 }
Ed Tanousb41187f2019-10-24 16:30:02 -070074 std::vector<std::string> paramVec = {params...};
zhanghch058d1b46d2021-04-01 11:18:24 +080075 doGet(asyncResp, req, paramVec);
Ed Tanousb41187f2019-10-24 16:30:02 -070076 });
Tanousf00032d2018-11-05 01:18:10 -030077
78 crow::DynamicRule& patch = app.routeDynamic(entityUrl.c_str());
79 patchRule = &patch;
Ed Tanousb41187f2019-10-24 16:30:02 -070080 patch.methods(boost::beast::http::verb::patch)(
zhanghch058d1b46d2021-04-01 11:18:24 +080081 [this](const crow::Request& req,
82 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousb41187f2019-10-24 16:30:02 -070083 Params... params) {
zhanghch058d1b46d2021-04-01 11:18:24 +080084 if (!redfishPreChecks(req, asyncResp))
Ed Tanous4df1bee2021-03-24 08:23:03 -070085 {
86 return;
87 }
Ed Tanousb41187f2019-10-24 16:30:02 -070088 std::vector<std::string> paramVec = {params...};
zhanghch058d1b46d2021-04-01 11:18:24 +080089 doPatch(asyncResp, req, paramVec);
Ed Tanousb41187f2019-10-24 16:30:02 -070090 });
Tanousf00032d2018-11-05 01:18:10 -030091
92 crow::DynamicRule& post = app.routeDynamic(entityUrl.c_str());
93 postRule = &post;
Ed Tanousb41187f2019-10-24 16:30:02 -070094 post.methods(boost::beast::http::verb::post)(
zhanghch058d1b46d2021-04-01 11:18:24 +080095 [this](const crow::Request& req,
96 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousb41187f2019-10-24 16:30:02 -070097 Params... params) {
zhanghch058d1b46d2021-04-01 11:18:24 +080098 if (!redfishPreChecks(req, asyncResp))
Ed Tanous4df1bee2021-03-24 08:23:03 -070099 {
100 return;
101 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700102 std::vector<std::string> paramVec = {params...};
zhanghch058d1b46d2021-04-01 11:18:24 +0800103 doPost(asyncResp, req, paramVec);
Ed Tanousb41187f2019-10-24 16:30:02 -0700104 });
Tanousf00032d2018-11-05 01:18:10 -0300105
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200106 crow::DynamicRule& put = app.routeDynamic(entityUrl.c_str());
107 putRule = &put;
108 put.methods(boost::beast::http::verb::put)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800109 [this](const crow::Request& req,
110 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200111 Params... params) {
zhanghch058d1b46d2021-04-01 11:18:24 +0800112 if (!redfishPreChecks(req, asyncResp))
Ed Tanous4df1bee2021-03-24 08:23:03 -0700113 {
114 return;
115 }
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200116 std::vector<std::string> paramVec = {params...};
zhanghch058d1b46d2021-04-01 11:18:24 +0800117 doPut(asyncResp, req, paramVec);
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200118 });
119
Ed Tanous2c70f802020-09-28 14:29:23 -0700120 crow::DynamicRule& deleteR = app.routeDynamic(entityUrl.c_str());
121 deleteRule = &deleteR;
122 deleteR.methods(boost::beast::http::verb::delete_)(
zhanghch058d1b46d2021-04-01 11:18:24 +0800123 [this](const crow::Request& req,
124 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Ed Tanousb41187f2019-10-24 16:30:02 -0700125 Params... params) {
zhanghch058d1b46d2021-04-01 11:18:24 +0800126 if (!redfishPreChecks(req, asyncResp))
Ed Tanous4df1bee2021-03-24 08:23:03 -0700127 {
128 return;
129 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700130 std::vector<std::string> paramVec = {params...};
zhanghch058d1b46d2021-04-01 11:18:24 +0800131 doDelete(asyncResp, req, paramVec);
Ed Tanousb41187f2019-10-24 16:30:02 -0700132 });
Tanousf00032d2018-11-05 01:18:10 -0300133 }
134
135 void initPrivileges()
136 {
137 auto it = entityPrivileges.find(boost::beast::http::verb::get);
138 if (it != entityPrivileges.end())
139 {
140 if (getRule != nullptr)
141 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000142 getRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300143 }
144 }
145 it = entityPrivileges.find(boost::beast::http::verb::post);
146 if (it != entityPrivileges.end())
147 {
148 if (postRule != nullptr)
149 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000150 postRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300151 }
152 }
153 it = entityPrivileges.find(boost::beast::http::verb::patch);
154 if (it != entityPrivileges.end())
155 {
156 if (patchRule != nullptr)
157 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000158 patchRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300159 }
160 }
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200161 it = entityPrivileges.find(boost::beast::http::verb::put);
162 if (it != entityPrivileges.end())
163 {
164 if (putRule != nullptr)
165 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000166 putRule->privileges(it->second);
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200167 }
168 }
Tanousf00032d2018-11-05 01:18:10 -0300169 it = entityPrivileges.find(boost::beast::http::verb::delete_);
170 if (it != entityPrivileges.end())
171 {
172 if (deleteRule != nullptr)
173 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000174 deleteRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300175 }
176 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100177 }
Ed Tanouscbbfa962018-03-13 16:46:28 -0700178
Ed Tanous1abe55e2018-09-05 08:30:59 -0700179 virtual ~Node() = default;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100180
Ed Tanous1abe55e2018-09-05 08:30:59 -0700181 OperationMap entityPrivileges;
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100182
Tanousf00032d2018-11-05 01:18:10 -0300183 crow::DynamicRule* getRule = nullptr;
184 crow::DynamicRule* postRule = nullptr;
185 crow::DynamicRule* patchRule = nullptr;
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200186 crow::DynamicRule* putRule = nullptr;
Tanousf00032d2018-11-05 01:18:10 -0300187 crow::DynamicRule* deleteRule = nullptr;
188
Ed Tanous1abe55e2018-09-05 08:30:59 -0700189 protected:
zhanghch058d1b46d2021-04-01 11:18:24 +0800190 App& app;
Ed Tanous1abe55e2018-09-05 08:30:59 -0700191 // Node is designed to be an abstract class, so doGet is pure virtual
zhanghch058d1b46d2021-04-01 11:18:24 +0800192 virtual void doGet(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
193 const crow::Request&, const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700194 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800195 asyncResp->res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100196 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700197
zhanghch058d1b46d2021-04-01 11:18:24 +0800198 virtual void doPatch(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
199 const crow::Request&, const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700200 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800201 asyncResp->res.result(boost::beast::http::status::method_not_allowed);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700202 }
203
zhanghch058d1b46d2021-04-01 11:18:24 +0800204 virtual void doPost(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
205 const crow::Request&, const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700206 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800207 asyncResp->res.result(boost::beast::http::status::method_not_allowed);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700208 }
209
zhanghch058d1b46d2021-04-01 11:18:24 +0800210 virtual void doPut(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
211 const crow::Request&, const std::vector<std::string>&)
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200212 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800213 asyncResp->res.result(boost::beast::http::status::method_not_allowed);
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200214 }
215
zhanghch058d1b46d2021-04-01 11:18:24 +0800216 virtual void doDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
217 const crow::Request&, const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700218 {
zhanghch058d1b46d2021-04-01 11:18:24 +0800219 asyncResp->res.result(boost::beast::http::status::method_not_allowed);
Ed Tanous1abe55e2018-09-05 08:30:59 -0700220 }
Joseph Reynolds900f9492019-11-25 15:37:29 -0600221
Joseph Reynolds3bf4e632020-02-06 14:44:32 -0600222 /* @brief Would the operation be allowed if the user did not have the
223 * ConfigureSelf Privilege? Also honors session.isConfigureSelfOnly.
Joseph Reynolds900f9492019-11-25 15:37:29 -0600224 *
225 * @param req the request
226 *
227 * @returns True if allowed, false otherwise
228 */
229 inline bool isAllowedWithoutConfigureSelf(const crow::Request& req)
230 {
RAJESWARAN THILLAIGOVINDAN61dbeef2019-12-13 04:26:54 -0600231 const std::string& userRole = req.userRole;
232 BMCWEB_LOG_DEBUG << "isAllowedWithoutConfigureSelf for the role "
233 << req.userRole;
Joseph Reynolds3bf4e632020-02-06 14:44:32 -0600234 Privileges effectiveUserPrivileges;
235 if (req.session && req.session->isConfigureSelfOnly)
236 {
237 // The session has no privileges because it is limited to
238 // configureSelfOnly and we are disregarding that privilege.
239 // Note that some operations do not require any privilege.
240 }
241 else
242 {
243 effectiveUserPrivileges = redfish::getUserPrivileges(userRole);
244 effectiveUserPrivileges.resetSinglePrivilege("ConfigureSelf");
245 }
Joseph Reynolds900f9492019-11-25 15:37:29 -0600246 const auto& requiredPrivilegesIt = entityPrivileges.find(req.method());
247 return (requiredPrivilegesIt != entityPrivileges.end()) &&
248 isOperationAllowedWithPrivileges(requiredPrivilegesIt->second,
249 effectiveUserPrivileges);
250 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100251};
252
Ed Tanous1abe55e2018-09-05 08:30:59 -0700253} // namespace redfish