summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-phosphor/interfaces/bmcweb/0020-EventService-Validate-SSE-query-filters.patch
blob: 8f3e1fc9bbf26cd0fd875f3444bd11cd456b191f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
From 5fd71f098aad2f6d64e94343738c43ffdff5709e Mon Sep 17 00:00:00 2001
From: AppaRao Puli <apparao.puli@linux.intel.com>
Date: Tue, 8 Sep 2020 16:19:30 +0530
Subject: [PATCH] EventService: Validate SSE query filters

Validate the query filters which are specified in
requested url and return with error if not supported.
Also RegistryPrefix and MessageId are mutually exclusive
as per redfish specification. so return error if user
specifies both.

Tested:
 - Checked with invalid query filters and it returns
   the error.

Change-Id: If07341f39d8c6b9bc229baae966f8569ebdd7b19
Signed-off-by: AppaRao Puli <apparao.puli@linux.intel.com>
---
 redfish-core/include/error_messages.hpp            |  9 ++
 .../include/registries/base_message_registry.hpp   | 14 ++-
 redfish-core/lib/event_service.hpp                 | 99 +++++++++++++++-------
 redfish-core/src/error_messages.cpp                | 26 ++++++
 4 files changed, 116 insertions(+), 32 deletions(-)

diff --git a/redfish-core/include/error_messages.hpp b/redfish-core/include/error_messages.hpp
index 9a2d1ca..fd6bb48 100644
--- a/redfish-core/include/error_messages.hpp
+++ b/redfish-core/include/error_messages.hpp
@@ -801,6 +801,15 @@ nlohmann::json mutualExclusiveProperties(const std::string& arg1,
 void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
                                const std::string& arg2);
 
+/**
+ * @brief Formats InvalidQueryFilter message into JSON
+ * Message body: "The requested URL contains the invalid query filters"
+ *
+ * @returns Message InvalidQueryFilter formatted to JSON */
+nlohmann::json invalidQueryFilter();
+
+void invalidQueryFilter(crow::Response& res);
+
 } // namespace messages
 
 } // namespace redfish
diff --git a/redfish-core/include/registries/base_message_registry.hpp b/redfish-core/include/registries/base_message_registry.hpp
index 7c385a0..18085c8 100644
--- a/redfish-core/include/registries/base_message_registry.hpp
+++ b/redfish-core/include/registries/base_message_registry.hpp
@@ -36,7 +36,7 @@ const Header header = {
 constexpr const char* url =
     "https://redfish.dmtf.org/registries/Base.1.8.1.json";
 
-constexpr std::array<MessageEntry, 74> registry = {
+constexpr std::array<MessageEntry, 75> registry = {
     MessageEntry{
         "AccessDenied",
         {
@@ -403,6 +403,18 @@ constexpr std::array<MessageEntry, 74> registry = {
             "Either the object is malformed or the URI is not correct.  "
             "Correct the condition and resubmit the request if it failed.",
         }},
+    MessageEntry{
+        "InvalidQueryFilter",
+        {
+            "Indicates the request url contains invalid query filter.",
+            "The requested url contains the invalid query filter.",
+            "Warning",
+            "Warning",
+            0,
+            {},
+            "Ensure the correct query filter is specified in requested url "
+            "and resubmit the request if the operation failed.",
+        }},
     MessageEntry{"MalformedJSON",
                  {
                      "Indicates that the request body was malformed JSON.  "
diff --git a/redfish-core/lib/event_service.hpp b/redfish-core/lib/event_service.hpp
index f14c03e..b91b745 100644
--- a/redfish-core/lib/event_service.hpp
+++ b/redfish-core/lib/event_service.hpp
@@ -462,73 +462,110 @@ class EventServiceSSE : public Node
             return;
         }
 
-        std::shared_ptr<crow::Request::Adaptor> sseConn =
-            std::make_shared<crow::Request::Adaptor>(std::move(req.socket()));
-        std::shared_ptr<Subscription> subValue =
-            std::make_shared<Subscription>(sseConn);
-
-        // GET on this URI means, Its SSE subscriptionType.
-        subValue->subscriptionType = subscriptionTypeSSE;
-
-        // Default values
-        subValue->protocol = "Redfish";
-        subValue->retryPolicy = "TerminateAfterRetries";
-
-        boost::urls::url_view::params_type::iterator it =
-            req.urlParams.find("$filter");
-        if (it == req.urlParams.end())
+        // It supports only "$filter" query param.
+        if (req.urlParams.size() > 1)
         {
-            subValue->eventFormatType = "Event";
+            messages::invalidQueryFilter(res);
+            res.end();
+            return;
         }
 
+        std::string eventFormatType;
+        std::string queryFilters;
+        if (req.urlParams.size())
+        {
+            boost::urls::url_view::params_type::iterator it =
+                req.urlParams.find("$filter");
+            if (it == req.urlParams.end())
+            {
+                messages::invalidQueryFilter(res);
+                res.end();
+                return;
+            }
+            else
+            {
+                queryFilters = it->value();
+            }
+        }
         else
         {
-            std::string filters = it->value();
-            // Reading from query params.
-            bool status = readSSEQueryParams(
-                filters, subValue->eventFormatType, subValue->registryMsgIds,
-                subValue->registryPrefixes, subValue->metricReportDefinitions);
+            eventFormatType = "Event";
+        }
 
+        std::vector<std::string> msgIds;
+        std::vector<std::string> regPrefixes;
+        std::vector<std::string> mrdsArray;
+        if (!queryFilters.empty())
+        {
+            // Reading from query params.
+            bool status = readSSEQueryParams(queryFilters, eventFormatType,
+                                             msgIds, regPrefixes, mrdsArray);
             if (!status)
             {
-                messages::invalidObject(res, filters);
+                messages::invalidObject(res, queryFilters);
+                res.end();
                 return;
             }
 
-            if (!subValue->eventFormatType.empty())
+            // RegsitryPrefix and messageIds are mutuly exclusive as per redfish
+            // specification.
+            if (regPrefixes.size() && msgIds.size())
+            {
+                messages::mutualExclusiveProperties(res, "RegistryPrefix",
+                                                    "MessageId");
+                res.end();
+                return;
+            }
+
+            if (!eventFormatType.empty())
             {
                 if (std::find(supportedEvtFormatTypes.begin(),
                               supportedEvtFormatTypes.end(),
-                              subValue->eventFormatType) ==
-                    supportedEvtFormatTypes.end())
+                              eventFormatType) == supportedEvtFormatTypes.end())
                 {
-                    messages::propertyValueNotInList(
-                        res, subValue->eventFormatType, "EventFormatType");
+                    messages::propertyValueNotInList(res, eventFormatType,
+                                                     "EventFormatType");
+                    res.end();
                     return;
                 }
             }
             else
             {
                 // If nothing specified, using default "Event"
-                subValue->eventFormatType.assign({"Event"});
+                eventFormatType.assign({"Event"});
             }
 
-            if (!subValue->registryPrefixes.empty())
+            if (!regPrefixes.empty())
             {
-                for (const std::string& it : subValue->registryPrefixes)
+                for (const std::string& it : regPrefixes)
                 {
                     if (std::find(supportedRegPrefixes.begin(),
                                   supportedRegPrefixes.end(),
                                   it) == supportedRegPrefixes.end())
                     {
                         messages::propertyValueNotInList(res, it,
-                                                         "RegistryPrefixes");
+                                                         "RegistryPrefix");
+                        res.end();
                         return;
                     }
                 }
             }
         }
 
+        std::shared_ptr<crow::Request::Adaptor> sseConn =
+            std::make_shared<crow::Request::Adaptor>(std::move(req.socket()));
+        std::shared_ptr<Subscription> subValue =
+            std::make_shared<Subscription>(sseConn);
+
+        // GET on this URI means, Its SSE subscriptionType.
+        subValue->subscriptionType = subscriptionTypeSSE;
+        subValue->protocol = "Redfish";
+        subValue->retryPolicy = "TerminateAfterRetries";
+        subValue->eventFormatType = eventFormatType;
+        subValue->registryMsgIds = msgIds;
+        subValue->registryPrefixes = regPrefixes;
+        subValue->metricReportDefinitions = mrdsArray;
+
         std::string id =
             EventServiceManager::getInstance().addSubscription(subValue, false);
         if (id.empty())
diff --git a/redfish-core/src/error_messages.cpp b/redfish-core/src/error_messages.cpp
index c6938ba..290d3f2 100644
--- a/redfish-core/src/error_messages.cpp
+++ b/redfish-core/src/error_messages.cpp
@@ -1779,6 +1779,32 @@ void mutualExclusiveProperties(crow::Response& res, const std::string& arg1,
     addMessageToErrorJson(res.jsonValue, mutualExclusiveProperties(arg1, arg2));
 }
 
+/**
+ * @internal
+ * @brief Formats InvalidQueryFilter into JSON
+ *
+ * See header file for more information
+ * @endinternal
+ */
+nlohmann::json invalidQueryFilter()
+{
+    return nlohmann::json{
+        {"@odata.type", "#Message.v1_0_0.Message"},
+        {"MessageId", "Base.1.5.0.InvalidQueryFilter"},
+        {"Message", "The requested url contains the invalid query filter."},
+        {"MessageArgs", nlohmann::json::array()},
+        {"Severity", "Warning"},
+        {"Resolution",
+         "Ensure the correct query filter is specified in requested url "
+         "and resubmit the request."}};
+}
+
+void invalidQueryFilter(crow::Response& res)
+{
+    res.result(boost::beast::http::status::bad_request);
+    addMessageToErrorJson(res.jsonValue, invalidQueryFilter());
+}
+
 } // namespace messages
 
 } // namespace redfish
-- 
2.7.4