blob: 43506d5b3126e911ccdb15fa3f642b6f3b6a66ae [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
Ed Tanous04e438c2020-10-03 08:06:26 -070018#include "http_request.hpp"
19#include "http_response.hpp"
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010020#include "privileges.hpp"
Ed Tanousa8c4ce92021-03-24 08:44:51 -070021#include "redfish_v1.hpp"
Ed Tanous1abe55e2018-09-05 08:30:59 -070022
Ed Tanousa0803ef2018-08-29 13:29:23 -070023#include <error_messages.hpp>
Ed Tanousa8c4ce92021-03-24 08:44:51 -070024#include <rf_async_resp.hpp>
Ed Tanousa0803ef2018-08-29 13:29:23 -070025
Gunnar Mills1214b7e2020-06-04 10:11:30 -050026#include <vector>
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010027
Ed Tanous1abe55e2018-09-05 08:30:59 -070028namespace redfish
29{
Borawski.Lukasz86e1b662018-01-19 14:22:14 +010030
31/**
32 * @brief Abstract class used for implementing Redfish nodes.
33 *
34 */
Ed Tanous1abe55e2018-09-05 08:30:59 -070035class Node
36{
Ed Tanous4df1bee2021-03-24 08:23:03 -070037 private:
38 bool redfishPreChecks(const crow::Request& req, crow::Response& res)
39 {
40 std::string_view odataHeader = req.getHeaderValue("OData-Version");
41 if (odataHeader.empty())
42 {
43 // Clients aren't required to provide odata version
44 return true;
45 }
46 if (odataHeader != "4.0")
47 {
48 redfish::messages::preconditionFailed(res);
49 res.end();
50 return false;
51 }
52
53 res.addHeader("OData-Version", "4.0");
54 return true;
55 }
56
Ed Tanous1abe55e2018-09-05 08:30:59 -070057 public:
58 template <typename... Params>
Ed Tanouscb13a392020-07-25 19:02:03 +000059 Node(App& app, std::string&& entityUrl, [[maybe_unused]] Params... paramsIn)
Ed Tanous1abe55e2018-09-05 08:30:59 -070060 {
Tanousf00032d2018-11-05 01:18:10 -030061 crow::DynamicRule& get = app.routeDynamic(entityUrl.c_str());
62 getRule = &get;
Ed Tanousb41187f2019-10-24 16:30:02 -070063 get.methods(boost::beast::http::verb::get)(
64 [this](const crow::Request& req, crow::Response& res,
65 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -070066 if (!redfishPreChecks(req, res))
67 {
68 return;
69 }
Ed Tanousb41187f2019-10-24 16:30:02 -070070 std::vector<std::string> paramVec = {params...};
71 doGet(res, req, paramVec);
72 });
Tanousf00032d2018-11-05 01:18:10 -030073
74 crow::DynamicRule& patch = app.routeDynamic(entityUrl.c_str());
75 patchRule = &patch;
Ed Tanousb41187f2019-10-24 16:30:02 -070076 patch.methods(boost::beast::http::verb::patch)(
77 [this](const crow::Request& req, crow::Response& res,
78 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -070079 if (!redfishPreChecks(req, res))
80 {
81 return;
82 }
Ed Tanousb41187f2019-10-24 16:30:02 -070083 std::vector<std::string> paramVec = {params...};
84 doPatch(res, req, paramVec);
85 });
Tanousf00032d2018-11-05 01:18:10 -030086
87 crow::DynamicRule& post = app.routeDynamic(entityUrl.c_str());
88 postRule = &post;
Ed Tanousb41187f2019-10-24 16:30:02 -070089 post.methods(boost::beast::http::verb::post)(
90 [this](const crow::Request& req, crow::Response& res,
91 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -070092 if (!redfishPreChecks(req, res))
93 {
94 return;
95 }
Ed Tanousb41187f2019-10-24 16:30:02 -070096 std::vector<std::string> paramVec = {params...};
97 doPost(res, req, paramVec);
98 });
Tanousf00032d2018-11-05 01:18:10 -030099
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200100 crow::DynamicRule& put = app.routeDynamic(entityUrl.c_str());
101 putRule = &put;
102 put.methods(boost::beast::http::verb::put)(
103 [this](const crow::Request& req, crow::Response& res,
104 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -0700105 if (!redfishPreChecks(req, res))
106 {
107 return;
108 }
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200109 std::vector<std::string> paramVec = {params...};
110 doPut(res, req, paramVec);
111 });
112
Ed Tanous2c70f802020-09-28 14:29:23 -0700113 crow::DynamicRule& deleteR = app.routeDynamic(entityUrl.c_str());
114 deleteRule = &deleteR;
115 deleteR.methods(boost::beast::http::verb::delete_)(
Ed Tanousb41187f2019-10-24 16:30:02 -0700116 [this](const crow::Request& req, crow::Response& res,
117 Params... params) {
Ed Tanous4df1bee2021-03-24 08:23:03 -0700118 if (!redfishPreChecks(req, res))
119 {
120 return;
121 }
Ed Tanousb41187f2019-10-24 16:30:02 -0700122 std::vector<std::string> paramVec = {params...};
123 doDelete(res, req, paramVec);
124 });
Tanousf00032d2018-11-05 01:18:10 -0300125 }
126
127 void initPrivileges()
128 {
129 auto it = entityPrivileges.find(boost::beast::http::verb::get);
130 if (it != entityPrivileges.end())
131 {
132 if (getRule != nullptr)
133 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000134 getRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300135 }
136 }
137 it = entityPrivileges.find(boost::beast::http::verb::post);
138 if (it != entityPrivileges.end())
139 {
140 if (postRule != nullptr)
141 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000142 postRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300143 }
144 }
145 it = entityPrivileges.find(boost::beast::http::verb::patch);
146 if (it != entityPrivileges.end())
147 {
148 if (patchRule != nullptr)
149 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000150 patchRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300151 }
152 }
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200153 it = entityPrivileges.find(boost::beast::http::verb::put);
154 if (it != entityPrivileges.end())
155 {
156 if (putRule != nullptr)
157 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000158 putRule->privileges(it->second);
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200159 }
160 }
Tanousf00032d2018-11-05 01:18:10 -0300161 it = entityPrivileges.find(boost::beast::http::verb::delete_);
162 if (it != entityPrivileges.end())
163 {
164 if (deleteRule != nullptr)
165 {
Ed Tanous23a21a12020-07-25 04:45:05 +0000166 deleteRule->privileges(it->second);
Tanousf00032d2018-11-05 01:18:10 -0300167 }
168 }
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100169 }
Ed Tanouscbbfa962018-03-13 16:46:28 -0700170
Ed Tanous1abe55e2018-09-05 08:30:59 -0700171 virtual ~Node() = default;
Borawski.Lukaszc1a46bd2018-02-08 13:31:59 +0100172
Ed Tanous1abe55e2018-09-05 08:30:59 -0700173 OperationMap entityPrivileges;
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100174
Tanousf00032d2018-11-05 01:18:10 -0300175 crow::DynamicRule* getRule = nullptr;
176 crow::DynamicRule* postRule = nullptr;
177 crow::DynamicRule* patchRule = nullptr;
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200178 crow::DynamicRule* putRule = nullptr;
Tanousf00032d2018-11-05 01:18:10 -0300179 crow::DynamicRule* deleteRule = nullptr;
180
Ed Tanous1abe55e2018-09-05 08:30:59 -0700181 protected:
182 // Node is designed to be an abstract class, so doGet is pure virtual
Ed Tanouscb13a392020-07-25 19:02:03 +0000183 virtual void doGet(crow::Response& res, const crow::Request&,
184 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700185 {
186 res.result(boost::beast::http::status::method_not_allowed);
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100187 res.end();
188 }
Ed Tanous1abe55e2018-09-05 08:30:59 -0700189
Ed Tanouscb13a392020-07-25 19:02:03 +0000190 virtual void doPatch(crow::Response& res, const crow::Request&,
191 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700192 {
193 res.result(boost::beast::http::status::method_not_allowed);
194 res.end();
195 }
196
Ed Tanouscb13a392020-07-25 19:02:03 +0000197 virtual void doPost(crow::Response& res, const crow::Request&,
198 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700199 {
200 res.result(boost::beast::http::status::method_not_allowed);
201 res.end();
202 }
203
Ed Tanouscb13a392020-07-25 19:02:03 +0000204 virtual void doPut(crow::Response& res, const crow::Request&,
205 const std::vector<std::string>&)
Adrian Ambrożewicz15302612020-07-16 11:24:47 +0200206 {
207 res.result(boost::beast::http::status::method_not_allowed);
208 res.end();
209 }
210
Ed Tanouscb13a392020-07-25 19:02:03 +0000211 virtual void doDelete(crow::Response& res, const crow::Request&,
212 const std::vector<std::string>&)
Ed Tanous1abe55e2018-09-05 08:30:59 -0700213 {
214 res.result(boost::beast::http::status::method_not_allowed);
215 res.end();
216 }
Joseph Reynolds900f9492019-11-25 15:37:29 -0600217
Joseph Reynolds3bf4e632020-02-06 14:44:32 -0600218 /* @brief Would the operation be allowed if the user did not have the
219 * ConfigureSelf Privilege? Also honors session.isConfigureSelfOnly.
Joseph Reynolds900f9492019-11-25 15:37:29 -0600220 *
221 * @param req the request
222 *
223 * @returns True if allowed, false otherwise
224 */
225 inline bool isAllowedWithoutConfigureSelf(const crow::Request& req)
226 {
RAJESWARAN THILLAIGOVINDAN61dbeef2019-12-13 04:26:54 -0600227 const std::string& userRole = req.userRole;
228 BMCWEB_LOG_DEBUG << "isAllowedWithoutConfigureSelf for the role "
229 << req.userRole;
Joseph Reynolds3bf4e632020-02-06 14:44:32 -0600230 Privileges effectiveUserPrivileges;
231 if (req.session && req.session->isConfigureSelfOnly)
232 {
233 // The session has no privileges because it is limited to
234 // configureSelfOnly and we are disregarding that privilege.
235 // Note that some operations do not require any privilege.
236 }
237 else
238 {
239 effectiveUserPrivileges = redfish::getUserPrivileges(userRole);
240 effectiveUserPrivileges.resetSinglePrivilege("ConfigureSelf");
241 }
Joseph Reynolds900f9492019-11-25 15:37:29 -0600242 const auto& requiredPrivilegesIt = entityPrivileges.find(req.method());
243 return (requiredPrivilegesIt != entityPrivileges.end()) &&
244 isOperationAllowedWithPrivileges(requiredPrivilegesIt->second,
245 effectiveUserPrivileges);
246 }
Borawski.Lukasz86e1b662018-01-19 14:22:14 +0100247};
248
Ed Tanous1abe55e2018-09-05 08:30:59 -0700249} // namespace redfish