]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
9f95a23c | 2 | // vim: ts=8 sw=2 smarttab ft=cpp |
11fdf7f2 TL |
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" | |
20effc67 | 18 | #include "rgw_sal.h" |
9f95a23c | 19 | #include "services/svc_zone.h" |
11fdf7f2 TL |
20 | |
21 | #define dout_subsys ceph_subsys_rgw | |
22 | ||
20effc67 | 23 | using namespace std; |
11fdf7f2 TL |
24 | using rgw::IAM::Policy; |
25 | ||
26 | void RGWRestUserPolicy::dump(Formatter *f) const | |
27 | { | |
2a845540 TL |
28 | encode_json("PolicyName", policy_name , f); |
29 | encode_json("UserName", user_name , f); | |
30 | encode_json("PolicyDocument", policy, f); | |
11fdf7f2 TL |
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 | ||
f67539c2 | 42 | int RGWRestUserPolicy::verify_permission(optional_yield y) |
11fdf7f2 TL |
43 | { |
44 | if (s->auth.identity->is_anonymous()) { | |
45 | return -EACCES; | |
46 | } | |
47 | ||
9f95a23c | 48 | if(int ret = check_caps(s->user->get_caps()); ret == 0) { |
11fdf7f2 TL |
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); | |
eafe8130 | 55 | if (! verify_user_permission(this, s, rgw::ARN(rgw::ARN(user_id.id, |
11fdf7f2 TL |
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) { | |
b3b6e05e | 66 | ldpp_dout(this, 0) << "ERROR: Invalid policy name length " << dendl; |
11fdf7f2 TL |
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)) { | |
b3b6e05e | 72 | ldpp_dout(this, 0) << "ERROR: Invalid chars in policy name " << dendl; |
11fdf7f2 TL |
73 | return false; |
74 | } | |
75 | ||
76 | return true; | |
77 | } | |
78 | ||
9f95a23c | 79 | int RGWUserPolicyRead::check_caps(const RGWUserCaps& caps) |
11fdf7f2 TL |
80 | { |
81 | return caps.check_cap("user-policy", RGW_CAP_READ); | |
82 | } | |
83 | ||
9f95a23c | 84 | int RGWUserPolicyWrite::check_caps(const RGWUserCaps& caps) |
11fdf7f2 TL |
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 | { | |
eafe8130 TL |
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); | |
11fdf7f2 TL |
99 | |
100 | if (policy_name.empty() || user_name.empty() || policy.empty()) { | |
b3b6e05e | 101 | ldpp_dout(this, 20) << "ERROR: one of policy name, user name or policy document is empty" |
11fdf7f2 TL |
102 | << dendl; |
103 | return -EINVAL; | |
104 | } | |
105 | ||
106 | if (! validate_input()) { | |
107 | return -EINVAL; | |
108 | } | |
109 | ||
110 | return 0; | |
111 | } | |
112 | ||
f67539c2 | 113 | void RGWPutUserPolicy::execute(optional_yield y) |
11fdf7f2 TL |
114 | { |
115 | op_ret = get_params(); | |
116 | if (op_ret < 0) { | |
117 | return; | |
118 | } | |
119 | ||
120 | bufferlist bl = bufferlist::static_from_string(policy); | |
121 | ||
20effc67 TL |
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); | |
11fdf7f2 TL |
125 | if (op_ret < 0) { |
126 | op_ret = -ERR_NO_SUCH_ENTITY; | |
127 | return; | |
128 | } | |
129 | ||
20effc67 | 130 | op_ret = user->read_attrs(s, s->yield); |
11fdf7f2 TL |
131 | if (op_ret == -ENOENT) { |
132 | op_ret = -ERR_NO_SUCH_ENTITY; | |
133 | return; | |
134 | } | |
135 | ||
f67539c2 | 136 | ceph::bufferlist in_data; |
b3b6e05e | 137 | op_ret = store->forward_request_to_master(this, s->user.get(), nullptr, in_data, nullptr, s->info, y); |
f67539c2 TL |
138 | if (op_ret < 0) { |
139 | ldpp_dout(this, 0) << "ERROR: forward_request_to_master returned ret=" << op_ret << dendl; | |
140 | return; | |
9f95a23c TL |
141 | } |
142 | ||
11fdf7f2 | 143 | try { |
9f95a23c | 144 | const Policy p(s->cct, s->user->get_tenant(), bl); |
11fdf7f2 | 145 | map<string, string> policies; |
20effc67 TL |
146 | if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) { |
147 | bufferlist out_bl = it->second; | |
11fdf7f2 TL |
148 | decode(policies, out_bl); |
149 | } | |
150 | bufferlist in_bl; | |
151 | policies[policy_name] = policy; | |
152 | encode(policies, in_bl); | |
20effc67 | 153 | user->get_attrs()[RGW_ATTR_USER_POLICY] = in_bl; |
11fdf7f2 | 154 | |
20effc67 | 155 | op_ret = user->store_user(s, s->yield, false); |
11fdf7f2 TL |
156 | if (op_ret < 0) { |
157 | op_ret = -ERR_INTERNAL_ERROR; | |
158 | } | |
159 | } catch (rgw::IAM::PolicyParseException& e) { | |
b3b6e05e | 160 | ldpp_dout(this, 20) << "failed to parse policy: " << e.what() << dendl; |
11fdf7f2 TL |
161 | op_ret = -ERR_MALFORMED_DOC; |
162 | } | |
92f5a8d4 TL |
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 | } | |
11fdf7f2 TL |
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()) { | |
b3b6e05e | 184 | ldpp_dout(this, 20) << "ERROR: one of policy name or user name is empty" |
11fdf7f2 TL |
185 | << dendl; |
186 | return -EINVAL; | |
187 | } | |
188 | ||
189 | return 0; | |
190 | } | |
191 | ||
f67539c2 | 192 | void RGWGetUserPolicy::execute(optional_yield y) |
11fdf7f2 TL |
193 | { |
194 | op_ret = get_params(); | |
195 | if (op_ret < 0) { | |
196 | return; | |
197 | } | |
198 | ||
20effc67 TL |
199 | std::unique_ptr<rgw::sal::User> user = store->get_user(rgw_user(user_name)); |
200 | op_ret = user->read_attrs(s, s->yield); | |
11fdf7f2 | 201 | if (op_ret == -ENOENT) { |
b3b6e05e | 202 | ldpp_dout(this, 0) << "ERROR: attrs not found for user" << user_name << dendl; |
11fdf7f2 TL |
203 | op_ret = -ERR_NO_SUCH_ENTITY; |
204 | return; | |
205 | } | |
206 | ||
207 | if (op_ret == 0) { | |
92f5a8d4 TL |
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"); | |
11fdf7f2 | 213 | map<string, string> policies; |
20effc67 TL |
214 | if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) { |
215 | bufferlist bl = it->second; | |
11fdf7f2 TL |
216 | decode(policies, bl); |
217 | if (auto it = policies.find(policy_name); it != policies.end()) { | |
218 | policy = policies[policy_name]; | |
11fdf7f2 | 219 | dump(s->formatter); |
11fdf7f2 | 220 | } else { |
b3b6e05e | 221 | ldpp_dout(this, 0) << "ERROR: policy not found" << policy << dendl; |
11fdf7f2 TL |
222 | op_ret = -ERR_NO_SUCH_ENTITY; |
223 | return; | |
224 | } | |
225 | } else { | |
b3b6e05e | 226 | ldpp_dout(this, 0) << "ERROR: RGW_ATTR_USER_POLICY not found" << dendl; |
11fdf7f2 TL |
227 | op_ret = -ERR_NO_SUCH_ENTITY; |
228 | return; | |
229 | } | |
92f5a8d4 TL |
230 | s->formatter->close_section(); |
231 | s->formatter->close_section(); | |
11fdf7f2 TL |
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()) { | |
b3b6e05e | 248 | ldpp_dout(this, 20) << "ERROR: user name is empty" << dendl; |
11fdf7f2 TL |
249 | return -EINVAL; |
250 | } | |
251 | ||
252 | return 0; | |
253 | } | |
254 | ||
f67539c2 | 255 | void RGWListUserPolicies::execute(optional_yield y) |
11fdf7f2 TL |
256 | { |
257 | op_ret = get_params(); | |
258 | if (op_ret < 0) { | |
259 | return; | |
260 | } | |
261 | ||
20effc67 TL |
262 | std::unique_ptr<rgw::sal::User> user = store->get_user(rgw_user(user_name)); |
263 | op_ret = user->read_attrs(s, s->yield); | |
11fdf7f2 | 264 | if (op_ret == -ENOENT) { |
b3b6e05e | 265 | ldpp_dout(this, 0) << "ERROR: attrs not found for user" << user_name << dendl; |
11fdf7f2 TL |
266 | op_ret = -ERR_NO_SUCH_ENTITY; |
267 | return; | |
268 | } | |
269 | ||
270 | if (op_ret == 0) { | |
271 | map<string, string> policies; | |
20effc67 | 272 | if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) { |
92f5a8d4 TL |
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"); | |
20effc67 | 278 | bufferlist bl = it->second; |
2a845540 TL |
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"); | |
11fdf7f2 | 287 | for (const auto& p : policies) { |
92f5a8d4 | 288 | s->formatter->dump_string("member", p.first); |
11fdf7f2 | 289 | } |
92f5a8d4 TL |
290 | s->formatter->close_section(); |
291 | s->formatter->close_section(); | |
2a845540 | 292 | s->formatter->close_section(); |
11fdf7f2 | 293 | } else { |
b3b6e05e | 294 | ldpp_dout(this, 0) << "ERROR: RGW_ATTR_USER_POLICY not found" << dendl; |
11fdf7f2 TL |
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()) { | |
b3b6e05e | 315 | ldpp_dout(this, 20) << "ERROR: One of policy name or user name is empty"<< dendl; |
11fdf7f2 TL |
316 | return -EINVAL; |
317 | } | |
318 | ||
319 | return 0; | |
320 | } | |
321 | ||
f67539c2 | 322 | void RGWDeleteUserPolicy::execute(optional_yield y) |
11fdf7f2 TL |
323 | { |
324 | op_ret = get_params(); | |
325 | if (op_ret < 0) { | |
326 | return; | |
327 | } | |
328 | ||
20effc67 TL |
329 | std::unique_ptr<rgw::sal::User> user = store->get_user(rgw_user(user_name)); |
330 | op_ret = user->load_user(s, s->yield); | |
11fdf7f2 TL |
331 | if (op_ret < 0) { |
332 | op_ret = -ERR_NO_SUCH_ENTITY; | |
333 | return; | |
334 | } | |
335 | ||
20effc67 TL |
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 | ||
f67539c2 | 342 | ceph::bufferlist in_data; |
b3b6e05e | 343 | op_ret = store->forward_request_to_master(this, s->user.get(), nullptr, in_data, nullptr, s->info, y); |
f67539c2 TL |
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; | |
9f95a23c | 350 | } |
f67539c2 | 351 | ldpp_dout(this, 0) << "ERROR: forward_request_to_master returned ret=" << op_ret << dendl; |
11fdf7f2 TL |
352 | } |
353 | ||
354 | map<string, string> policies; | |
20effc67 TL |
355 | if (auto it = user->get_attrs().find(RGW_ATTR_USER_POLICY); it != user->get_attrs().end()) { |
356 | bufferlist out_bl = it->second; | |
11fdf7f2 TL |
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); | |
20effc67 TL |
363 | user->get_attrs()[RGW_ATTR_USER_POLICY] = in_bl; |
364 | ||
365 | op_ret = user->store_user(s, s->yield, false); | |
11fdf7f2 TL |
366 | if (op_ret < 0) { |
367 | op_ret = -ERR_INTERNAL_ERROR; | |
368 | } | |
92f5a8d4 TL |
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 | } | |
11fdf7f2 TL |
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 | } |