]> git.proxmox.com Git - ceph.git/blame - ceph/src/rgw/rgw_role.cc
update sources to v12.1.0
[ceph.git] / ceph / src / rgw / rgw_role.cc
CommitLineData
7c673cae
FG
1#include <errno.h>
2#include <ctime>
3
31f18b77
FG
4#include <boost/regex.hpp>
5
7c673cae
FG
6#include "common/errno.h"
7#include "common/Formatter.h"
8#include "common/ceph_json.h"
9#include "common/ceph_time.h"
10#include "rgw_rados.h"
11
12#include "include/types.h"
13#include "rgw_string.h"
14
15#include "rgw_common.h"
16#include "rgw_tools.h"
17#include "rgw_role.h"
18
19#define dout_subsys ceph_subsys_rgw
20
21using namespace std;
22
23const string RGWRole::role_name_oid_prefix = "role_names.";
24const string RGWRole::role_oid_prefix = "roles.";
25const string RGWRole::role_path_oid_prefix = "role_paths.";
26const string RGWRole::role_arn_prefix = "arn:aws:iam::";
27
28int RGWRole::store_info(bool exclusive)
29{
30 string oid = get_info_oid_prefix() + id;
31
32 bufferlist bl;
33 ::encode(*this, bl);
34 return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid,
35 bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL);
36}
37
38int RGWRole::store_name(bool exclusive)
39{
40 RGWNameToId nameToId;
41 nameToId.obj_id = id;
42
31f18b77 43 string oid = tenant + get_names_oid_prefix() + name;
7c673cae
FG
44
45 bufferlist bl;
46 ::encode(nameToId, bl);
47 return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid,
48 bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL);
49}
50
51int RGWRole::store_path(bool exclusive)
52{
31f18b77 53 string oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id;
7c673cae
FG
54
55 return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid,
56 NULL, 0, exclusive, NULL, real_time(), NULL);
57}
58
59int RGWRole::create(bool exclusive)
60{
61 int ret;
62
31f18b77
FG
63 if (! validate_input()) {
64 return -EINVAL;
65 }
66
7c673cae 67 /* check to see the name is not used */
31f18b77 68 ret = read_id(name, tenant, id);
7c673cae
FG
69 if (exclusive && ret == 0) {
70 ldout(cct, 0) << "ERROR: name " << name << " already in use for role id "
71 << id << dendl;
72 return -EEXIST;
73 } else if ( ret < 0 && ret != -ENOENT) {
74 ldout(cct, 0) << "failed reading role id " << id << ": "
75 << cpp_strerror(-ret) << dendl;
76 return ret;
77 }
78
79 /* create unique id */
80 uuid_d new_uuid;
81 char uuid_str[37];
82 new_uuid.generate_random();
83 new_uuid.print(uuid_str);
84 id = uuid_str;
85
86 //arn
31f18b77 87 arn = role_arn_prefix + tenant + ":role" + path + name;
7c673cae
FG
88
89 // Creation time
90 real_clock::time_point t = real_clock::now();
91
92 struct timeval tv;
93 real_clock::to_timeval(t, tv);
94
95 char buf[30];
96 struct tm result;
97 gmtime_r(&tv.tv_sec, &result);
98 strftime(buf,30,"%Y-%m-%dT%H:%M:%S", &result);
99 sprintf(buf + strlen(buf),".%dZ",(int)tv.tv_usec/1000);
100 creation_date.assign(buf, strlen(buf));
101
102 auto& pool = store->get_zone_params().roles_pool;
103 ret = store_info(exclusive);
104 if (ret < 0) {
105 ldout(cct, 0) << "ERROR: storing role info in pool: " << pool.name << ": "
106 << id << ": " << cpp_strerror(-ret) << dendl;
107 return ret;
108 }
109
110 ret = store_name(exclusive);
111 if (ret < 0) {
112 ldout(cct, 0) << "ERROR: storing role name in pool: " << pool.name << ": "
113 << name << ": " << cpp_strerror(-ret) << dendl;
114
115 //Delete the role info that was stored in the previous call
116 string oid = get_info_oid_prefix() + id;
117 int info_ret = rgw_delete_system_obj(store, pool, oid, NULL);
118 if (info_ret < 0) {
119 ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": "
120 << id << ": " << cpp_strerror(-info_ret) << dendl;
121 }
122 return ret;
123 }
124
125 ret = store_path(exclusive);
126 if (ret < 0) {
127 ldout(cct, 0) << "ERROR: storing role path in pool: " << pool.name << ": "
128 << path << ": " << cpp_strerror(-ret) << dendl;
129 //Delete the role info that was stored in the previous call
130 string oid = get_info_oid_prefix() + id;
131 int info_ret = rgw_delete_system_obj(store, pool, oid, NULL);
132 if (info_ret < 0) {
133 ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": "
134 << id << ": " << cpp_strerror(-info_ret) << dendl;
135 }
136 //Delete role name that was stored in previous call
31f18b77 137 oid = tenant + get_names_oid_prefix() + name;
7c673cae
FG
138 int name_ret = rgw_delete_system_obj(store, pool, oid, NULL);
139 if (name_ret < 0) {
140 ldout(cct, 0) << "ERROR: cleanup of role name from pool: " << pool.name << ": "
141 << name << ": " << cpp_strerror(-name_ret) << dendl;
142 }
143 return ret;
144 }
145 return 0;
146}
147
148int RGWRole::delete_obj()
149{
150 auto& pool = store->get_zone_params().roles_pool;
151
152 int ret = read_name();
153 if (ret < 0) {
154 return ret;
155 }
156
157 ret = read_info();
158 if (ret < 0) {
159 return ret;
160 }
161
162 if (! perm_policy_map.empty()) {
163 return -ERR_DELETE_CONFLICT;
164 }
165
166 // Delete id
167 string oid = get_info_oid_prefix() + id;
168 ret = rgw_delete_system_obj(store, pool, oid, NULL);
169 if (ret < 0) {
170 ldout(cct, 0) << "ERROR: deleting role id from pool: " << pool.name << ": "
171 << id << ": " << cpp_strerror(-ret) << dendl;
172 }
173
174 // Delete name
31f18b77 175 oid = tenant + get_names_oid_prefix() + name;
7c673cae
FG
176 ret = rgw_delete_system_obj(store, pool, oid, NULL);
177 if (ret < 0) {
178 ldout(cct, 0) << "ERROR: deleting role name from pool: " << pool.name << ": "
179 << name << ": " << cpp_strerror(-ret) << dendl;
180 }
181
182 // Delete path
31f18b77 183 oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id;
7c673cae
FG
184 ret = rgw_delete_system_obj(store, pool, oid, NULL);
185 if (ret < 0) {
186 ldout(cct, 0) << "ERROR: deleting role path from pool: " << pool.name << ": "
187 << path << ": " << cpp_strerror(-ret) << dendl;
188 }
189 return ret;
190}
191
192int RGWRole::get()
193{
194 int ret = read_name();
195 if (ret < 0) {
196 return ret;
197 }
198
199 ret = read_info();
200 if (ret < 0) {
201 return ret;
202 }
203
204 return 0;
205}
206
31f18b77
FG
207int RGWRole::get_by_id()
208{
209 int ret = read_info();
210 if (ret < 0) {
211 return ret;
212 }
213
214 return 0;
215}
216
7c673cae
FG
217int RGWRole::update()
218{
219 auto& pool = store->get_zone_params().roles_pool;
220
221 int ret = store_info(false);
222 if (ret < 0) {
223 ldout(cct, 0) << "ERROR: storing info in pool: " << pool.name << ": "
224 << id << ": " << cpp_strerror(-ret) << dendl;
225 return ret;
226 }
227
228 return 0;
229}
230
231void RGWRole::set_perm_policy(const string& policy_name, const string& perm_policy)
232{
233 perm_policy_map[policy_name] = perm_policy;
234}
235
236vector<string> RGWRole::get_role_policy_names()
237{
238 vector<string> policy_names;
239 for (const auto& it : perm_policy_map)
240 {
241 policy_names.push_back(std::move(it.first));
242 }
243
244 return policy_names;
245}
246
247int RGWRole::get_role_policy(const string& policy_name, string& perm_policy)
248{
249 const auto it = perm_policy_map.find(policy_name);
250 if (it == perm_policy_map.end()) {
251 ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl;
252 return -EINVAL;
253 } else {
254 perm_policy = it->second;
255 }
256 return 0;
257}
258
259int RGWRole::delete_policy(const string& policy_name)
260{
261 const auto& it = perm_policy_map.find(policy_name);
262 if (it == perm_policy_map.end()) {
263 ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl;
264 return -ENOENT;
265 } else {
266 perm_policy_map.erase(it);
267 }
268 return 0;
269}
270
271void RGWRole::dump(Formatter *f) const
272{
273 encode_json("id", id , f);
274 encode_json("name", name , f);
275 encode_json("path", path, f);
276 encode_json("arn", arn, f);
277 encode_json("create_date", creation_date, f);
278 encode_json("assume_role_policy_document", trust_policy, f);
279}
280
281void RGWRole::decode_json(JSONObj *obj)
282{
283 JSONDecoder::decode_json("id", id, obj);
284 JSONDecoder::decode_json("name", name, obj);
285 JSONDecoder::decode_json("path", path, obj);
286 JSONDecoder::decode_json("arn", arn, obj);
287 JSONDecoder::decode_json("create_date", creation_date, obj);
288 JSONDecoder::decode_json("assume_role_policy_document", trust_policy, obj);
289}
290
31f18b77 291int RGWRole::read_id(const string& role_name, const string& tenant, string& role_id)
7c673cae
FG
292{
293 auto& pool = store->get_zone_params().roles_pool;
31f18b77 294 string oid = tenant + get_names_oid_prefix() + role_name;
7c673cae
FG
295 bufferlist bl;
296 RGWObjectCtx obj_ctx(store);
297
298 int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
299 if (ret < 0) {
300 return ret;
301 }
302
303 RGWNameToId nameToId;
304 try {
305 bufferlist::iterator iter = bl.begin();
306 ::decode(nameToId, iter);
307 } catch (buffer::error& err) {
308 ldout(cct, 0) << "ERROR: failed to decode role from pool: " << pool.name << ": "
309 << role_name << dendl;
310 return -EIO;
311 }
312 role_id = nameToId.obj_id;
313 return 0;
314}
315
316int RGWRole::read_info()
317{
318 auto& pool = store->get_zone_params().roles_pool;
319 string oid = get_info_oid_prefix() + id;
320 bufferlist bl;
321 RGWObjectCtx obj_ctx(store);
322
323 int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
324 if (ret < 0) {
325 ldout(cct, 0) << "ERROR: failed reading role info from pool: " << pool.name <<
326 ": " << id << ": " << cpp_strerror(-ret) << dendl;
327 return ret;
328 }
329
330 try {
331 bufferlist::iterator iter = bl.begin();
332 ::decode(*this, iter);
333 } catch (buffer::error& err) {
334 ldout(cct, 0) << "ERROR: failed to decode role info from pool: " << pool.name <<
335 ": " << id << dendl;
336 return -EIO;
337 }
338
339 return 0;
340}
341
342int RGWRole::read_name()
343{
344 auto& pool = store->get_zone_params().roles_pool;
31f18b77 345 string oid = tenant + get_names_oid_prefix() + name;
7c673cae
FG
346 bufferlist bl;
347 RGWObjectCtx obj_ctx(store);
348
349 int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
350 if (ret < 0) {
351 ldout(cct, 0) << "ERROR: failed reading role name from pool: " << pool.name << ": "
352 << name << ": " << cpp_strerror(-ret) << dendl;
353 return ret;
354 }
355
356 RGWNameToId nameToId;
357 try {
358 bufferlist::iterator iter = bl.begin();
359 ::decode(nameToId, iter);
360 } catch (buffer::error& err) {
361 ldout(cct, 0) << "ERROR: failed to decode role name from pool: " << pool.name << ": "
362 << name << dendl;
363 return -EIO;
364 }
365 id = nameToId.obj_id;
366 return 0;
367}
368
31f18b77
FG
369bool RGWRole::validate_input()
370{
371 if (name.length() > MAX_ROLE_NAME_LEN) {
372 ldout(cct, 0) << "ERROR: Invalid name length " << dendl;
373 return false;
374 }
375
376 if (path.length() > MAX_PATH_NAME_LEN) {
377 ldout(cct, 0) << "ERROR: Invalid path length " << dendl;
378 return false;
379 }
380
381 boost::regex regex_name("[A-Za-z0-9:=,.@-]+");
382 if (! boost::regex_match(name, regex_name)) {
383 ldout(cct, 0) << "ERROR: Invalid chars in name " << dendl;
384 return false;
385 }
386
387 boost::regex regex_path("(/[!-~]+/)|(/)");
388 if (! boost::regex_match(path,regex_path)) {
389 ldout(cct, 0) << "ERROR: Invalid chars in path " << dendl;
390 return false;
391 }
392
393 return true;
394}
395
396void RGWRole::extract_name_tenant(const std::string& str)
397{
398 size_t pos = str.find('$');
399 if (pos != std::string::npos) {
400 tenant = str.substr(0, pos);
401 name = str.substr(pos + 1);
402 }
403}
404
7c673cae
FG
405void RGWRole::update_trust_policy(string& trust_policy)
406{
407 this->trust_policy = trust_policy;
408}
409
31f18b77
FG
410int RGWRole::get_roles_by_path_prefix(RGWRados *store,
411 CephContext *cct,
412 const string& path_prefix,
413 const string& tenant,
414 vector<RGWRole>& roles)
7c673cae
FG
415{
416 auto pool = store->get_zone_params().roles_pool;
417 string prefix;
418
419 // List all roles if path prefix is empty
420 if (! path_prefix.empty()) {
31f18b77 421 prefix = tenant + role_path_oid_prefix + path_prefix;
7c673cae 422 } else {
31f18b77 423 prefix = tenant + role_path_oid_prefix;
7c673cae
FG
424 }
425
426 //Get the filtered objects
427 list<string> result;
428 bool is_truncated;
429 RGWListRawObjsCtx ctx;
430 do {
431 list<string> oids;
432 int r = store->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated);
433 if (r < 0) {
434 ldout(cct, 0) << "ERROR: listing filtered objects failed: " << pool.name << ": "
435 << prefix << ": " << cpp_strerror(-r) << dendl;
436 return r;
437 }
438 for (const auto& iter : oids) {
439 result.push_back(iter.substr(role_path_oid_prefix.size()));
440 }
441 } while (is_truncated);
442
443 for (const auto& it : result) {
444 //Find the role oid prefix from the end
445 size_t pos = it.rfind(role_oid_prefix);
446 if (pos == string::npos) {
447 continue;
448 }
449 // Split the result into path and info_oid + id
450 string path = it.substr(0, pos);
451
452 /*Make sure that prefix is part of path (False results could've been returned)
453 because of the role info oid + id appended to the path)*/
454 if(path_prefix.empty() || path.find(path_prefix) != string::npos) {
455 //Get id from info oid prefix + id
456 string id = it.substr(pos + role_oid_prefix.length());
457
458 RGWRole role(cct, store);
459 role.set_id(id);
460 int ret = role.read_info();
461 if (ret < 0) {
462 return ret;
463 }
464 roles.push_back(std::move(role));
465 }
466 }
467
468 return 0;
469}
470
471const string& RGWRole::get_names_oid_prefix()
472{
473 return role_name_oid_prefix;
474}
475
476const string& RGWRole::get_info_oid_prefix()
477{
478 return role_oid_prefix;
479}
480
481const string& RGWRole::get_path_oid_prefix()
482{
483 return role_path_oid_prefix;
484}