]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_rest_user_policy.cc
import ceph quincy 17.2.4
[ceph.git] / ceph / src / rgw / rgw_rest_user_policy.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab ft=cpp
3
4 #include <errno.h>
5 #include <regex>
6
7 #include "common/errno.h"
8 #include "common/Formatter.h"
9 #include "common/ceph_json.h"
10
11 #include "include/types.h"
12 #include "rgw_string.h"
13
14 #include "rgw_common.h"
15 #include "rgw_op.h"
16 #include "rgw_rest.h"
17 #include "rgw_rest_user_policy.h"
18 #include "rgw_sal.h"
19 #include "services/svc_zone.h"
20
21 #define dout_subsys ceph_subsys_rgw
22
23 using namespace std;
24 using rgw::IAM::Policy;
25
26 void RGWRestUserPolicy::dump(Formatter *f) const
27 {
28 encode_json("PolicyName", policy_name , f);
29 encode_json("UserName", user_name , f);
30 encode_json("PolicyDocument", policy, f);
31 }
32
33 void RGWRestUserPolicy::send_response()
34 {
35 if (op_ret) {
36 set_req_state_err(s, op_ret);
37 }
38 dump_errno(s);
39 end_header(s);
40 }
41
42 int RGWRestUserPolicy::verify_permission(optional_yield y)
43 {
44 if (s->auth.identity->is_anonymous()) {
45 return -EACCES;
46 }
47
48 if(int ret = check_caps(s->user->get_caps()); ret == 0) {
49 return ret;
50 }
51
52 uint64_t op = get_op();
53 string user_name = s->info.args.get("UserName");
54 rgw_user user_id(user_name);
55 if (! verify_user_permission(this, s, rgw::ARN(rgw::ARN(user_id.id,
56 "user",
57 user_id.tenant)), op)) {
58 return -EACCES;
59 }
60 return 0;
61 }
62
63 bool RGWRestUserPolicy::validate_input()
64 {
65 if (policy_name.length() > MAX_POLICY_NAME_LEN) {
66 ldpp_dout(this, 0) << "ERROR: Invalid policy name length " << dendl;
67 return false;
68 }
69
70 std::regex regex_policy_name("[A-Za-z0-9:=,.@-]+");
71 if (! std::regex_match(policy_name, regex_policy_name)) {
72 ldpp_dout(this, 0) << "ERROR: Invalid chars in policy name " << dendl;
73 return false;
74 }
75
76 return true;
77 }
78
79 int RGWUserPolicyRead::check_caps(const RGWUserCaps& caps)
80 {
81 return caps.check_cap("user-policy", RGW_CAP_READ);
82 }
83
84 int RGWUserPolicyWrite::check_caps(const RGWUserCaps& caps)
85 {
86 return caps.check_cap("user-policy", RGW_CAP_WRITE);
87 }
88
89 uint64_t RGWPutUserPolicy::get_op()
90 {
91 return rgw::IAM::iamPutUserPolicy;
92 }
93
94 int RGWPutUserPolicy::get_params()
95 {
96 policy_name = url_decode(s->info.args.get("PolicyName"), true);
97 user_name = url_decode(s->info.args.get("UserName"), true);
98 policy = url_decode(s->info.args.get("PolicyDocument"), true);
99
100 if (policy_name.empty() || user_name.empty() || policy.empty()) {
101 ldpp_dout(this, 20) << "ERROR: one of policy name, user name or policy document is empty"
102 << dendl;
103 return -EINVAL;
104 }
105
106 if (! validate_input()) {
107 return -EINVAL;
108 }
109
110 return 0;
111 }
112
113 void RGWPutUserPolicy::execute(optional_yield y)
114 {
115 op_ret = get_params();
116 if (op_ret < 0) {
117 return;
118 }
119
120 bufferlist bl = bufferlist::static_from_string(policy);
121
122 std::unique_ptr<rgw::sal::User> user = store->get_user(rgw_user(user_name));
123
124 op_ret = user->load_user(s, s->yield);
125 if (op_ret < 0) {
126 op_ret = -ERR_NO_SUCH_ENTITY;
127 return;
128 }
129
130 op_ret = user->read_attrs(s, s->yield);
131 if (op_ret == -ENOENT) {
132 op_ret = -ERR_NO_SUCH_ENTITY;
133 return;
134 }
135
136 ceph::bufferlist in_data;
137 op_ret = store->forward_request_to_master(this, s->user.get(), nullptr, in_data, nullptr, s->info, y);
138 if (op_ret < 0) {
139 ldpp_dout(this, 0) << "ERROR: forward_request_to_master returned ret=" << op_ret << dendl;
140 return;
141 }
142
143 try {
144 const Policy p(s->cct, s->user->get_tenant(), bl);
145 map<string, string> policies;
146 if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) {
147 bufferlist out_bl = it->second;
148 decode(policies, out_bl);
149 }
150 bufferlist in_bl;
151 policies[policy_name] = policy;
152 encode(policies, in_bl);
153 user->get_attrs()[RGW_ATTR_USER_POLICY] = in_bl;
154
155 op_ret = user->store_user(s, s->yield, false);
156 if (op_ret < 0) {
157 op_ret = -ERR_INTERNAL_ERROR;
158 }
159 } catch (rgw::IAM::PolicyParseException& e) {
160 ldpp_dout(this, 20) << "failed to parse policy: " << e.what() << dendl;
161 op_ret = -ERR_MALFORMED_DOC;
162 }
163
164 if (op_ret == 0) {
165 s->formatter->open_object_section("PutUserPolicyResponse");
166 s->formatter->open_object_section("ResponseMetadata");
167 s->formatter->dump_string("RequestId", s->trans_id);
168 s->formatter->close_section();
169 s->formatter->close_section();
170 }
171 }
172
173 uint64_t RGWGetUserPolicy::get_op()
174 {
175 return rgw::IAM::iamGetUserPolicy;
176 }
177
178 int RGWGetUserPolicy::get_params()
179 {
180 policy_name = s->info.args.get("PolicyName");
181 user_name = s->info.args.get("UserName");
182
183 if (policy_name.empty() || user_name.empty()) {
184 ldpp_dout(this, 20) << "ERROR: one of policy name or user name is empty"
185 << dendl;
186 return -EINVAL;
187 }
188
189 return 0;
190 }
191
192 void RGWGetUserPolicy::execute(optional_yield y)
193 {
194 op_ret = get_params();
195 if (op_ret < 0) {
196 return;
197 }
198
199 std::unique_ptr<rgw::sal::User> user = store->get_user(rgw_user(user_name));
200 op_ret = user->read_attrs(s, s->yield);
201 if (op_ret == -ENOENT) {
202 ldpp_dout(this, 0) << "ERROR: attrs not found for user" << user_name << dendl;
203 op_ret = -ERR_NO_SUCH_ENTITY;
204 return;
205 }
206
207 if (op_ret == 0) {
208 s->formatter->open_object_section("GetUserPolicyResponse");
209 s->formatter->open_object_section("ResponseMetadata");
210 s->formatter->dump_string("RequestId", s->trans_id);
211 s->formatter->close_section();
212 s->formatter->open_object_section("GetUserPolicyResult");
213 map<string, string> policies;
214 if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) {
215 bufferlist bl = it->second;
216 decode(policies, bl);
217 if (auto it = policies.find(policy_name); it != policies.end()) {
218 policy = policies[policy_name];
219 dump(s->formatter);
220 } else {
221 ldpp_dout(this, 0) << "ERROR: policy not found" << policy << dendl;
222 op_ret = -ERR_NO_SUCH_ENTITY;
223 return;
224 }
225 } else {
226 ldpp_dout(this, 0) << "ERROR: RGW_ATTR_USER_POLICY not found" << dendl;
227 op_ret = -ERR_NO_SUCH_ENTITY;
228 return;
229 }
230 s->formatter->close_section();
231 s->formatter->close_section();
232 }
233 if (op_ret < 0) {
234 op_ret = -ERR_INTERNAL_ERROR;
235 }
236 }
237
238 uint64_t RGWListUserPolicies::get_op()
239 {
240 return rgw::IAM::iamListUserPolicies;
241 }
242
243 int RGWListUserPolicies::get_params()
244 {
245 user_name = s->info.args.get("UserName");
246
247 if (user_name.empty()) {
248 ldpp_dout(this, 20) << "ERROR: user name is empty" << dendl;
249 return -EINVAL;
250 }
251
252 return 0;
253 }
254
255 void RGWListUserPolicies::execute(optional_yield y)
256 {
257 op_ret = get_params();
258 if (op_ret < 0) {
259 return;
260 }
261
262 std::unique_ptr<rgw::sal::User> user = store->get_user(rgw_user(user_name));
263 op_ret = user->read_attrs(s, s->yield);
264 if (op_ret == -ENOENT) {
265 ldpp_dout(this, 0) << "ERROR: attrs not found for user" << user_name << dendl;
266 op_ret = -ERR_NO_SUCH_ENTITY;
267 return;
268 }
269
270 if (op_ret == 0) {
271 map<string, string> policies;
272 if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) {
273 s->formatter->open_object_section("ListUserPoliciesResponse");
274 s->formatter->open_object_section("ResponseMetadata");
275 s->formatter->dump_string("RequestId", s->trans_id);
276 s->formatter->close_section();
277 s->formatter->open_object_section("ListUserPoliciesResult");
278 bufferlist bl = it->second;
279 try {
280 decode(policies, bl);
281 } catch (buffer::error& err) {
282 ldpp_dout(this, 0) << "ERROR: failed to decode user policies" << dendl;
283 op_ret = -EIO;
284 return;
285 }
286 s->formatter->open_object_section("PolicyNames");
287 for (const auto& p : policies) {
288 s->formatter->dump_string("member", p.first);
289 }
290 s->formatter->close_section();
291 s->formatter->close_section();
292 s->formatter->close_section();
293 } else {
294 ldpp_dout(this, 0) << "ERROR: RGW_ATTR_USER_POLICY not found" << dendl;
295 op_ret = -ERR_NO_SUCH_ENTITY;
296 return;
297 }
298 }
299 if (op_ret < 0) {
300 op_ret = -ERR_INTERNAL_ERROR;
301 }
302 }
303
304 uint64_t RGWDeleteUserPolicy::get_op()
305 {
306 return rgw::IAM::iamDeleteUserPolicy;
307 }
308
309 int RGWDeleteUserPolicy::get_params()
310 {
311 policy_name = s->info.args.get("PolicyName");
312 user_name = s->info.args.get("UserName");
313
314 if (policy_name.empty() || user_name.empty()) {
315 ldpp_dout(this, 20) << "ERROR: One of policy name or user name is empty"<< dendl;
316 return -EINVAL;
317 }
318
319 return 0;
320 }
321
322 void RGWDeleteUserPolicy::execute(optional_yield y)
323 {
324 op_ret = get_params();
325 if (op_ret < 0) {
326 return;
327 }
328
329 std::unique_ptr<rgw::sal::User> user = store->get_user(rgw_user(user_name));
330 op_ret = user->load_user(s, s->yield);
331 if (op_ret < 0) {
332 op_ret = -ERR_NO_SUCH_ENTITY;
333 return;
334 }
335
336 op_ret = user->read_attrs(this, s->yield);
337 if (op_ret == -ENOENT) {
338 op_ret = -ERR_NO_SUCH_ENTITY;
339 return;
340 }
341
342 ceph::bufferlist in_data;
343 op_ret = store->forward_request_to_master(this, s->user.get(), nullptr, in_data, nullptr, s->info, y);
344 if (op_ret < 0) {
345 // a policy might've been uploaded to this site when there was no sync
346 // req. in earlier releases, proceed deletion
347 if (op_ret != -ENOENT) {
348 ldpp_dout(this, 5) << "forward_request_to_master returned ret=" << op_ret << dendl;
349 return;
350 }
351 ldpp_dout(this, 0) << "ERROR: forward_request_to_master returned ret=" << op_ret << dendl;
352 }
353
354 map<string, string> policies;
355 if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) {
356 bufferlist out_bl = it->second;
357 decode(policies, out_bl);
358
359 if (auto p = policies.find(policy_name); p != policies.end()) {
360 bufferlist in_bl;
361 policies.erase(p);
362 encode(policies, in_bl);
363 user->get_attrs()[RGW_ATTR_USER_POLICY] = in_bl;
364
365 op_ret = user->store_user(s, s->yield, false);
366 if (op_ret < 0) {
367 op_ret = -ERR_INTERNAL_ERROR;
368 }
369 if (op_ret == 0) {
370 s->formatter->open_object_section("DeleteUserPoliciesResponse");
371 s->formatter->open_object_section("ResponseMetadata");
372 s->formatter->dump_string("RequestId", s->trans_id);
373 s->formatter->close_section();
374 s->formatter->close_section();
375 }
376 } else {
377 op_ret = -ERR_NO_SUCH_ENTITY;
378 return;
379 }
380 } else {
381 op_ret = -ERR_NO_SUCH_ENTITY;
382 return;
383 }
384 }