]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_rest_user_policy.cc
import ceph quincy 17.2.4
[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"
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 23using namespace std;
11fdf7f2
TL
24using rgw::IAM::Policy;
25
26void 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
33void 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 42int 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
63bool 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 79int RGWUserPolicyRead::check_caps(const RGWUserCaps& caps)
11fdf7f2
TL
80{
81 return caps.check_cap("user-policy", RGW_CAP_READ);
82}
83
9f95a23c 84int RGWUserPolicyWrite::check_caps(const RGWUserCaps& caps)
11fdf7f2
TL
85{
86 return caps.check_cap("user-policy", RGW_CAP_WRITE);
87}
88
89uint64_t RGWPutUserPolicy::get_op()
90{
91 return rgw::IAM::iamPutUserPolicy;
92}
93
94int 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 113void 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
173uint64_t RGWGetUserPolicy::get_op()
174{
175 return rgw::IAM::iamGetUserPolicy;
176}
177
178int 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 192void 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
238uint64_t RGWListUserPolicies::get_op()
239{
240 return rgw::IAM::iamListUserPolicies;
241}
242
243int 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 255void 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
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
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}