]> git.proxmox.com Git - ceph.git/blob - ceph/src/rgw/rgw_acl.cc
bump version to 18.2.4-pve3
[ceph.git] / ceph / src / rgw / rgw_acl.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 <string.h>
5
6 #include <iostream>
7 #include <map>
8
9 #include "include/types.h"
10
11 #include "common/Formatter.h"
12
13 #include "rgw_acl.h"
14 #include "rgw_acl_s3.h"
15 #include "rgw_user.h"
16
17 #define dout_subsys ceph_subsys_rgw
18
19 using namespace std;
20
21 bool operator==(const ACLPermission& lhs, const ACLPermission& rhs) {
22 return lhs.flags == rhs.flags;
23 }
24 bool operator!=(const ACLPermission& lhs, const ACLPermission& rhs) {
25 return !(lhs == rhs);
26 }
27
28 bool operator==(const ACLGranteeType& lhs, const ACLGranteeType& rhs) {
29 return lhs.type == rhs.type;
30 }
31 bool operator!=(const ACLGranteeType& lhs, const ACLGranteeType& rhs) {
32 return lhs.type != rhs.type;
33 }
34
35 bool operator==(const ACLGrant& lhs, const ACLGrant& rhs) {
36 return lhs.type == rhs.type && lhs.id == rhs.id
37 && lhs.email == rhs.email && lhs.permission == rhs.permission
38 && lhs.name == rhs.name && lhs.group == rhs.group
39 && lhs.url_spec == rhs.url_spec;
40 }
41 bool operator!=(const ACLGrant& lhs, const ACLGrant& rhs) {
42 return !(lhs == rhs);
43 }
44
45 bool operator==(const ACLReferer& lhs, const ACLReferer& rhs) {
46 return lhs.url_spec == rhs.url_spec && lhs.perm == rhs.perm;
47 }
48 bool operator!=(const ACLReferer& lhs, const ACLReferer& rhs) {
49 return !(lhs == rhs);
50 }
51
52 bool operator==(const RGWAccessControlList& lhs,
53 const RGWAccessControlList& rhs) {
54 return lhs.acl_user_map == rhs.acl_user_map
55 && lhs.acl_group_map == rhs.acl_group_map
56 && lhs.referer_list == rhs.referer_list
57 && lhs.grant_map == rhs.grant_map;
58 }
59 bool operator!=(const RGWAccessControlList& lhs,
60 const RGWAccessControlList& rhs) {
61 return !(lhs == rhs);
62 }
63
64 bool operator==(const ACLOwner& lhs, const ACLOwner& rhs) {
65 return lhs.id == rhs.id && lhs.display_name == rhs.display_name;
66 }
67 bool operator!=(const ACLOwner& lhs, const ACLOwner& rhs) {
68 return !(lhs == rhs);
69 }
70
71 bool operator==(const RGWAccessControlPolicy& lhs,
72 const RGWAccessControlPolicy& rhs) {
73 return lhs.acl == rhs.acl && lhs.owner == rhs.owner;
74 }
75 bool operator!=(const RGWAccessControlPolicy& lhs,
76 const RGWAccessControlPolicy& rhs) {
77 return !(lhs == rhs);
78 }
79
80 void RGWAccessControlList::_add_grant(ACLGrant *grant)
81 {
82 ACLPermission& perm = grant->get_permission();
83 ACLGranteeType& type = grant->get_type();
84 switch (type.get_type()) {
85 case ACL_TYPE_REFERER:
86 referer_list.emplace_back(grant->get_referer(), perm.get_permissions());
87
88 /* We're specially handling the Swift's .r:* as the S3 API has a similar
89 * concept and thus we can have a small portion of compatibility here. */
90 if (grant->get_referer() == RGW_REFERER_WILDCARD) {
91 acl_group_map[ACL_GROUP_ALL_USERS] |= perm.get_permissions();
92 }
93 break;
94 case ACL_TYPE_GROUP:
95 acl_group_map[grant->get_group()] |= perm.get_permissions();
96 break;
97 default:
98 {
99 rgw_user id;
100 if (!grant->get_id(id)) {
101 ldout(cct, 0) << "ERROR: grant->get_id() failed" << dendl;
102 }
103 acl_user_map[id.to_str()] |= perm.get_permissions();
104 }
105 }
106 }
107
108 void RGWAccessControlList::add_grant(ACLGrant *grant)
109 {
110 rgw_user id;
111 grant->get_id(id); // not that this will return false for groups, but that's ok, we won't search groups
112 grant_map.insert(pair<string, ACLGrant>(id.to_str(), *grant));
113 _add_grant(grant);
114 }
115
116 void RGWAccessControlList::remove_canon_user_grant(rgw_user& user_id)
117 {
118 auto multi_map_iter = grant_map.find(user_id.to_str());
119 if(multi_map_iter != grant_map.end()) {
120 auto grants = grant_map.equal_range(user_id.to_str());
121 grant_map.erase(grants.first, grants.second);
122 }
123
124 auto map_iter = acl_user_map.find(user_id.to_str());
125 if (map_iter != acl_user_map.end()){
126 acl_user_map.erase(map_iter);
127 }
128 }
129
130 uint32_t RGWAccessControlList::get_perm(const DoutPrefixProvider* dpp,
131 const rgw::auth::Identity& auth_identity,
132 const uint32_t perm_mask)
133 {
134 ldpp_dout(dpp, 5) << "Searching permissions for identity=" << auth_identity
135 << " mask=" << perm_mask << dendl;
136
137 return perm_mask & auth_identity.get_perms_from_aclspec(dpp, acl_user_map);
138 }
139
140 uint32_t RGWAccessControlList::get_group_perm(const DoutPrefixProvider *dpp,
141 ACLGroupTypeEnum group,
142 const uint32_t perm_mask) const
143 {
144 ldpp_dout(dpp, 5) << "Searching permissions for group=" << (int)group
145 << " mask=" << perm_mask << dendl;
146
147 const auto iter = acl_group_map.find((uint32_t)group);
148 if (iter != acl_group_map.end()) {
149 ldpp_dout(dpp, 5) << "Found permission: " << iter->second << dendl;
150 return iter->second & perm_mask;
151 }
152 ldpp_dout(dpp, 5) << "Permissions for group not found" << dendl;
153 return 0;
154 }
155
156 uint32_t RGWAccessControlList::get_referer_perm(const DoutPrefixProvider *dpp,
157 const uint32_t current_perm,
158 const std::string http_referer,
159 const uint32_t perm_mask)
160 {
161 ldpp_dout(dpp, 5) << "Searching permissions for referer=" << http_referer
162 << " mask=" << perm_mask << dendl;
163
164 /* This function is basically a transformation from current perm to
165 * a new one that takes into consideration the Swift's HTTP referer-
166 * based ACLs. We need to go through all items to respect negative
167 * grants. */
168 uint32_t referer_perm = current_perm;
169 for (const auto& r : referer_list) {
170 if (r.is_match(http_referer)) {
171 referer_perm = r.perm;
172 }
173 }
174
175 ldpp_dout(dpp, 5) << "Found referer permission=" << referer_perm << dendl;
176 return referer_perm & perm_mask;
177 }
178
179 uint32_t RGWAccessControlPolicy::get_perm(const DoutPrefixProvider* dpp,
180 const rgw::auth::Identity& auth_identity,
181 const uint32_t perm_mask,
182 const char * const http_referer,
183 bool ignore_public_acls)
184 {
185 ldpp_dout(dpp, 20) << "-- Getting permissions begin with perm_mask=" << perm_mask
186 << dendl;
187
188 uint32_t perm = acl.get_perm(dpp, auth_identity, perm_mask);
189
190 if (auth_identity.is_owner_of(owner.get_id())) {
191 perm |= perm_mask & (RGW_PERM_READ_ACP | RGW_PERM_WRITE_ACP);
192 }
193
194 if (perm == perm_mask) {
195 return perm;
196 }
197
198 /* should we continue looking up? */
199 if (!ignore_public_acls && ((perm & perm_mask) != perm_mask)) {
200 perm |= acl.get_group_perm(dpp, ACL_GROUP_ALL_USERS, perm_mask);
201
202 if (false == auth_identity.is_owner_of(rgw_user(RGW_USER_ANON_ID))) {
203 /* this is not the anonymous user */
204 perm |= acl.get_group_perm(dpp, ACL_GROUP_AUTHENTICATED_USERS, perm_mask);
205 }
206 }
207
208 /* Should we continue looking up even deeper? */
209 if (nullptr != http_referer && (perm & perm_mask) != perm_mask) {
210 perm = acl.get_referer_perm(dpp, perm, http_referer, perm_mask);
211 }
212
213 ldpp_dout(dpp, 5) << "-- Getting permissions done for identity=" << auth_identity
214 << ", owner=" << owner.get_id()
215 << ", perm=" << perm << dendl;
216
217 return perm;
218 }
219
220 bool RGWAccessControlPolicy::verify_permission(const DoutPrefixProvider* dpp,
221 const rgw::auth::Identity& auth_identity,
222 const uint32_t user_perm_mask,
223 const uint32_t perm,
224 const char * const http_referer,
225 bool ignore_public_acls)
226 {
227 uint32_t test_perm = perm | RGW_PERM_READ_OBJS | RGW_PERM_WRITE_OBJS;
228
229 uint32_t policy_perm = get_perm(dpp, auth_identity, test_perm, http_referer, ignore_public_acls);
230
231 /* the swift WRITE_OBJS perm is equivalent to the WRITE obj, just
232 convert those bits. Note that these bits will only be set on
233 buckets, so the swift READ permission on bucket will allow listing
234 the bucket content */
235 if (policy_perm & RGW_PERM_WRITE_OBJS) {
236 policy_perm |= (RGW_PERM_WRITE | RGW_PERM_WRITE_ACP);
237 }
238 if (policy_perm & RGW_PERM_READ_OBJS) {
239 policy_perm |= (RGW_PERM_READ | RGW_PERM_READ_ACP);
240 }
241
242 uint32_t acl_perm = policy_perm & perm & user_perm_mask;
243
244 ldpp_dout(dpp, 10) << " identity=" << auth_identity
245 << " requested perm (type)=" << perm
246 << ", policy perm=" << policy_perm
247 << ", user_perm_mask=" << user_perm_mask
248 << ", acl perm=" << acl_perm << dendl;
249
250 return (perm == acl_perm);
251 }
252
253
254 bool RGWAccessControlPolicy::is_public(const DoutPrefixProvider *dpp) const
255 {
256
257 static constexpr auto public_groups = {ACL_GROUP_ALL_USERS,
258 ACL_GROUP_AUTHENTICATED_USERS};
259 return std::any_of(public_groups.begin(), public_groups.end(),
260 [&, dpp](ACLGroupTypeEnum g) {
261 auto p = acl.get_group_perm(dpp, g, RGW_PERM_FULL_CONTROL);
262 return (p != RGW_PERM_NONE) && (p != RGW_PERM_INVALID);
263 }
264 );
265
266 }
267
268 void ACLPermission::generate_test_instances(list<ACLPermission*>& o)
269 {
270 ACLPermission *p = new ACLPermission;
271 p->set_permissions(RGW_PERM_WRITE_ACP);
272 o.push_back(p);
273 o.push_back(new ACLPermission);
274 }
275
276 void ACLPermission::dump(Formatter *f) const
277 {
278 f->dump_int("flags", flags);
279 }
280
281 void ACLGranteeType::dump(Formatter *f) const
282 {
283 f->dump_unsigned("type", type);
284 }
285
286 void ACLGrant::dump(Formatter *f) const
287 {
288 f->open_object_section("type");
289 type.dump(f);
290 f->close_section();
291
292 f->dump_string("id", id.to_str());
293 f->dump_string("email", email);
294
295 f->open_object_section("permission");
296 permission.dump(f);
297 f->close_section();
298
299 f->dump_string("name", name);
300 f->dump_int("group", (int)group);
301 f->dump_string("url_spec", url_spec);
302 }
303
304 void ACLGrant::generate_test_instances(list<ACLGrant*>& o)
305 {
306 rgw_user id("rgw");
307 string name, email;
308 name = "Mr. RGW";
309 email = "r@gw";
310
311 ACLGrant *g1 = new ACLGrant;
312 g1->set_canon(id, name, RGW_PERM_READ);
313 g1->email = email;
314 o.push_back(g1);
315
316 ACLGrant *g2 = new ACLGrant;
317 g1->set_group(ACL_GROUP_AUTHENTICATED_USERS, RGW_PERM_WRITE);
318 o.push_back(g2);
319
320 o.push_back(new ACLGrant);
321 }
322
323 void ACLGranteeType::generate_test_instances(list<ACLGranteeType*>& o)
324 {
325 ACLGranteeType *t = new ACLGranteeType;
326 t->set(ACL_TYPE_CANON_USER);
327 o.push_back(t);
328 o.push_back(new ACLGranteeType);
329 }
330
331 void RGWAccessControlList::generate_test_instances(list<RGWAccessControlList*>& o)
332 {
333 RGWAccessControlList *acl = new RGWAccessControlList(NULL);
334
335 list<ACLGrant *> glist;
336 list<ACLGrant *>::iterator iter;
337
338 ACLGrant::generate_test_instances(glist);
339 for (iter = glist.begin(); iter != glist.end(); ++iter) {
340 ACLGrant *grant = *iter;
341 acl->add_grant(grant);
342
343 delete grant;
344 }
345 o.push_back(acl);
346 o.push_back(new RGWAccessControlList(NULL));
347 }
348
349 void ACLOwner::generate_test_instances(list<ACLOwner*>& o)
350 {
351 ACLOwner *owner = new ACLOwner;
352 owner->id = "rgw";
353 owner->display_name = "Mr. RGW";
354 o.push_back(owner);
355 o.push_back(new ACLOwner);
356 }
357
358 void RGWAccessControlPolicy::generate_test_instances(list<RGWAccessControlPolicy*>& o)
359 {
360 list<RGWAccessControlList *> acl_list;
361 list<RGWAccessControlList *>::iterator iter;
362 for (iter = acl_list.begin(); iter != acl_list.end(); ++iter) {
363 RGWAccessControlList::generate_test_instances(acl_list);
364 iter = acl_list.begin();
365
366 RGWAccessControlPolicy *p = new RGWAccessControlPolicy(NULL);
367 RGWAccessControlList *l = *iter;
368 p->acl = *l;
369
370 string name = "radosgw";
371 rgw_user id("rgw");
372 p->owner.set_name(name);
373 p->owner.set_id(id);
374
375 o.push_back(p);
376
377 delete l;
378 }
379
380 o.push_back(new RGWAccessControlPolicy(NULL));
381 }
382
383 void RGWAccessControlList::dump(Formatter *f) const
384 {
385 map<string, int>::const_iterator acl_user_iter = acl_user_map.begin();
386 f->open_array_section("acl_user_map");
387 for (; acl_user_iter != acl_user_map.end(); ++acl_user_iter) {
388 f->open_object_section("entry");
389 f->dump_string("user", acl_user_iter->first);
390 f->dump_int("acl", acl_user_iter->second);
391 f->close_section();
392 }
393 f->close_section();
394
395 map<uint32_t, int>::const_iterator acl_group_iter = acl_group_map.begin();
396 f->open_array_section("acl_group_map");
397 for (; acl_group_iter != acl_group_map.end(); ++acl_group_iter) {
398 f->open_object_section("entry");
399 f->dump_unsigned("group", acl_group_iter->first);
400 f->dump_int("acl", acl_group_iter->second);
401 f->close_section();
402 }
403 f->close_section();
404
405 multimap<string, ACLGrant>::const_iterator giter = grant_map.begin();
406 f->open_array_section("grant_map");
407 for (; giter != grant_map.end(); ++giter) {
408 f->open_object_section("entry");
409 f->dump_string("id", giter->first);
410 f->open_object_section("grant");
411 giter->second.dump(f);
412 f->close_section();
413 f->close_section();
414 }
415 f->close_section();
416 }
417
418 void ACLOwner::dump(Formatter *f) const
419 {
420 encode_json("id", id.to_str(), f);
421 encode_json("display_name", display_name, f);
422 }
423
424 void ACLOwner::decode_json(JSONObj *obj) {
425 string id_str;
426 JSONDecoder::decode_json("id", id_str, obj);
427 id.from_str(id_str);
428 JSONDecoder::decode_json("display_name", display_name, obj);
429 }
430
431 void RGWAccessControlPolicy::dump(Formatter *f) const
432 {
433 encode_json("acl", acl, f);
434 encode_json("owner", owner, f);
435 }
436
437 ACLGroupTypeEnum ACLGrant::uri_to_group(string& uri)
438 {
439 // this is required for backward compatibility
440 return ACLGrant_S3::uri_to_group(uri);
441 }
442