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