4 #include <boost/regex.hpp>
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"
12 #include "include/types.h"
13 #include "rgw_string.h"
15 #include "rgw_common.h"
16 #include "rgw_tools.h"
19 #define dout_subsys ceph_subsys_rgw
23 const string RGWRole::role_name_oid_prefix = "role_names.";
24 const string RGWRole::role_oid_prefix = "roles.";
25 const string RGWRole::role_path_oid_prefix = "role_paths.";
26 const string RGWRole::role_arn_prefix = "arn:aws:iam::";
28 int RGWRole::store_info(bool exclusive)
30 string oid = get_info_oid_prefix() + id;
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);
38 int RGWRole::store_name(bool exclusive)
43 string oid = tenant + get_names_oid_prefix() + name;
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);
51 int RGWRole::store_path(bool exclusive)
53 string oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id;
55 return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid,
56 NULL, 0, exclusive, NULL, real_time(), NULL);
59 int RGWRole::create(bool exclusive)
63 if (! validate_input()) {
67 /* check to see the name is not used */
68 ret = read_id(name, tenant, id);
69 if (exclusive && ret == 0) {
70 ldout(cct, 0) << "ERROR: name " << name << " already in use for role id "
73 } else if ( ret < 0 && ret != -ENOENT) {
74 ldout(cct, 0) << "failed reading role id " << id << ": "
75 << cpp_strerror(-ret) << dendl;
79 /* create unique id */
82 new_uuid.generate_random();
83 new_uuid.print(uuid_str);
87 arn = role_arn_prefix + tenant + ":role" + path + name;
90 real_clock::time_point t = real_clock::now();
93 real_clock::to_timeval(t, tv);
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));
102 auto& pool = store->get_zone_params().roles_pool;
103 ret = store_info(exclusive);
105 ldout(cct, 0) << "ERROR: storing role info in pool: " << pool.name << ": "
106 << id << ": " << cpp_strerror(-ret) << dendl;
110 ret = store_name(exclusive);
112 ldout(cct, 0) << "ERROR: storing role name in pool: " << pool.name << ": "
113 << name << ": " << cpp_strerror(-ret) << dendl;
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);
119 ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": "
120 << id << ": " << cpp_strerror(-info_ret) << dendl;
125 ret = store_path(exclusive);
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);
133 ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": "
134 << id << ": " << cpp_strerror(-info_ret) << dendl;
136 //Delete role name that was stored in previous call
137 oid = tenant + get_names_oid_prefix() + name;
138 int name_ret = rgw_delete_system_obj(store, pool, oid, NULL);
140 ldout(cct, 0) << "ERROR: cleanup of role name from pool: " << pool.name << ": "
141 << name << ": " << cpp_strerror(-name_ret) << dendl;
148 int RGWRole::delete_obj()
150 auto& pool = store->get_zone_params().roles_pool;
152 int ret = read_name();
162 if (! perm_policy_map.empty()) {
163 return -ERR_DELETE_CONFLICT;
167 string oid = get_info_oid_prefix() + id;
168 ret = rgw_delete_system_obj(store, pool, oid, NULL);
170 ldout(cct, 0) << "ERROR: deleting role id from pool: " << pool.name << ": "
171 << id << ": " << cpp_strerror(-ret) << dendl;
175 oid = tenant + get_names_oid_prefix() + name;
176 ret = rgw_delete_system_obj(store, pool, oid, NULL);
178 ldout(cct, 0) << "ERROR: deleting role name from pool: " << pool.name << ": "
179 << name << ": " << cpp_strerror(-ret) << dendl;
183 oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id;
184 ret = rgw_delete_system_obj(store, pool, oid, NULL);
186 ldout(cct, 0) << "ERROR: deleting role path from pool: " << pool.name << ": "
187 << path << ": " << cpp_strerror(-ret) << dendl;
194 int ret = read_name();
207 int RGWRole::get_by_id()
209 int ret = read_info();
217 int RGWRole::update()
219 auto& pool = store->get_zone_params().roles_pool;
221 int ret = store_info(false);
223 ldout(cct, 0) << "ERROR: storing info in pool: " << pool.name << ": "
224 << id << ": " << cpp_strerror(-ret) << dendl;
231 void RGWRole::set_perm_policy(const string& policy_name, const string& perm_policy)
233 perm_policy_map[policy_name] = perm_policy;
236 vector<string> RGWRole::get_role_policy_names()
238 vector<string> policy_names;
239 for (const auto& it : perm_policy_map)
241 policy_names.push_back(std::move(it.first));
247 int RGWRole::get_role_policy(const string& policy_name, string& perm_policy)
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;
254 perm_policy = it->second;
259 int RGWRole::delete_policy(const string& policy_name)
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;
266 perm_policy_map.erase(it);
271 void RGWRole::dump(Formatter *f) const
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);
281 void RGWRole::decode_json(JSONObj *obj)
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);
291 int RGWRole::read_id(const string& role_name, const string& tenant, string& role_id)
293 auto& pool = store->get_zone_params().roles_pool;
294 string oid = tenant + get_names_oid_prefix() + role_name;
296 RGWObjectCtx obj_ctx(store);
298 int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
303 RGWNameToId nameToId;
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;
312 role_id = nameToId.obj_id;
316 int RGWRole::read_info()
318 auto& pool = store->get_zone_params().roles_pool;
319 string oid = get_info_oid_prefix() + id;
321 RGWObjectCtx obj_ctx(store);
323 int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
325 ldout(cct, 0) << "ERROR: failed reading role info from pool: " << pool.name <<
326 ": " << id << ": " << cpp_strerror(-ret) << dendl;
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 <<
342 int RGWRole::read_name()
344 auto& pool = store->get_zone_params().roles_pool;
345 string oid = tenant + get_names_oid_prefix() + name;
347 RGWObjectCtx obj_ctx(store);
349 int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL);
351 ldout(cct, 0) << "ERROR: failed reading role name from pool: " << pool.name << ": "
352 << name << ": " << cpp_strerror(-ret) << dendl;
356 RGWNameToId nameToId;
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 << ": "
365 id = nameToId.obj_id;
369 bool RGWRole::validate_input()
371 if (name.length() > MAX_ROLE_NAME_LEN) {
372 ldout(cct, 0) << "ERROR: Invalid name length " << dendl;
376 if (path.length() > MAX_PATH_NAME_LEN) {
377 ldout(cct, 0) << "ERROR: Invalid path length " << dendl;
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;
387 boost::regex regex_path("(/[!-~]+/)|(/)");
388 if (! boost::regex_match(path,regex_path)) {
389 ldout(cct, 0) << "ERROR: Invalid chars in path " << dendl;
396 void RGWRole::extract_name_tenant(const std::string& str)
398 size_t pos = str.find('$');
399 if (pos != std::string::npos) {
400 tenant = str.substr(0, pos);
401 name = str.substr(pos + 1);
405 void RGWRole::update_trust_policy(string& trust_policy)
407 this->trust_policy = trust_policy;
410 int RGWRole::get_roles_by_path_prefix(RGWRados *store,
412 const string& path_prefix,
413 const string& tenant,
414 vector<RGWRole>& roles)
416 auto pool = store->get_zone_params().roles_pool;
419 // List all roles if path prefix is empty
420 if (! path_prefix.empty()) {
421 prefix = tenant + role_path_oid_prefix + path_prefix;
423 prefix = tenant + role_path_oid_prefix;
426 //Get the filtered objects
429 RGWListRawObjsCtx ctx;
432 int r = store->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated);
434 ldout(cct, 0) << "ERROR: listing filtered objects failed: " << pool.name << ": "
435 << prefix << ": " << cpp_strerror(-r) << dendl;
438 for (const auto& iter : oids) {
439 result.push_back(iter.substr(role_path_oid_prefix.size()));
441 } while (is_truncated);
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) {
449 // Split the result into path and info_oid + id
450 string path = it.substr(0, pos);
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());
458 RGWRole role(cct, store);
460 int ret = role.read_info();
464 roles.push_back(std::move(role));
471 const string& RGWRole::get_names_oid_prefix()
473 return role_name_oid_prefix;
476 const string& RGWRole::get_info_oid_prefix()
478 return role_oid_prefix;
481 const string& RGWRole::get_path_oid_prefix()
483 return role_path_oid_prefix;