X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Frgw%2Frgw_role.cc;fp=src%2Fceph%2Fsrc%2Frgw%2Frgw_role.cc;h=732b49c7431ed99c2a4a2aed0227593aca6cd010;hb=812ff6ca9fcd3e629e49d4328905f33eee8ca3f5;hp=0000000000000000000000000000000000000000;hpb=15280273faafb77777eab341909a3f495cf248d9;p=stor4nfv.git diff --git a/src/ceph/src/rgw/rgw_role.cc b/src/ceph/src/rgw/rgw_role.cc new file mode 100644 index 0000000..732b49c --- /dev/null +++ b/src/ceph/src/rgw/rgw_role.cc @@ -0,0 +1,484 @@ +#include +#include + +#include + +#include "common/errno.h" +#include "common/Formatter.h" +#include "common/ceph_json.h" +#include "common/ceph_time.h" +#include "rgw_rados.h" + +#include "include/types.h" +#include "rgw_string.h" + +#include "rgw_common.h" +#include "rgw_tools.h" +#include "rgw_role.h" + +#define dout_subsys ceph_subsys_rgw + +using namespace std; + +const string RGWRole::role_name_oid_prefix = "role_names."; +const string RGWRole::role_oid_prefix = "roles."; +const string RGWRole::role_path_oid_prefix = "role_paths."; +const string RGWRole::role_arn_prefix = "arn:aws:iam::"; + +int RGWRole::store_info(bool exclusive) +{ + string oid = get_info_oid_prefix() + id; + + bufferlist bl; + ::encode(*this, bl); + return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid, + bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL); +} + +int RGWRole::store_name(bool exclusive) +{ + RGWNameToId nameToId; + nameToId.obj_id = id; + + string oid = tenant + get_names_oid_prefix() + name; + + bufferlist bl; + ::encode(nameToId, bl); + return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid, + bl.c_str(), bl.length(), exclusive, NULL, real_time(), NULL); +} + +int RGWRole::store_path(bool exclusive) +{ + string oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id; + + return rgw_put_system_obj(store, store->get_zone_params().roles_pool, oid, + NULL, 0, exclusive, NULL, real_time(), NULL); +} + +int RGWRole::create(bool exclusive) +{ + int ret; + + if (! validate_input()) { + return -EINVAL; + } + + /* check to see the name is not used */ + ret = read_id(name, tenant, id); + if (exclusive && ret == 0) { + ldout(cct, 0) << "ERROR: name " << name << " already in use for role id " + << id << dendl; + return -EEXIST; + } else if ( ret < 0 && ret != -ENOENT) { + ldout(cct, 0) << "failed reading role id " << id << ": " + << cpp_strerror(-ret) << dendl; + return ret; + } + + /* create unique id */ + uuid_d new_uuid; + char uuid_str[37]; + new_uuid.generate_random(); + new_uuid.print(uuid_str); + id = uuid_str; + + //arn + arn = role_arn_prefix + tenant + ":role" + path + name; + + // Creation time + real_clock::time_point t = real_clock::now(); + + struct timeval tv; + real_clock::to_timeval(t, tv); + + char buf[30]; + struct tm result; + gmtime_r(&tv.tv_sec, &result); + strftime(buf,30,"%Y-%m-%dT%H:%M:%S", &result); + sprintf(buf + strlen(buf),".%dZ",(int)tv.tv_usec/1000); + creation_date.assign(buf, strlen(buf)); + + auto& pool = store->get_zone_params().roles_pool; + ret = store_info(exclusive); + if (ret < 0) { + ldout(cct, 0) << "ERROR: storing role info in pool: " << pool.name << ": " + << id << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + + ret = store_name(exclusive); + if (ret < 0) { + ldout(cct, 0) << "ERROR: storing role name in pool: " << pool.name << ": " + << name << ": " << cpp_strerror(-ret) << dendl; + + //Delete the role info that was stored in the previous call + string oid = get_info_oid_prefix() + id; + int info_ret = rgw_delete_system_obj(store, pool, oid, NULL); + if (info_ret < 0) { + ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": " + << id << ": " << cpp_strerror(-info_ret) << dendl; + } + return ret; + } + + ret = store_path(exclusive); + if (ret < 0) { + ldout(cct, 0) << "ERROR: storing role path in pool: " << pool.name << ": " + << path << ": " << cpp_strerror(-ret) << dendl; + //Delete the role info that was stored in the previous call + string oid = get_info_oid_prefix() + id; + int info_ret = rgw_delete_system_obj(store, pool, oid, NULL); + if (info_ret < 0) { + ldout(cct, 0) << "ERROR: cleanup of role id from pool: " << pool.name << ": " + << id << ": " << cpp_strerror(-info_ret) << dendl; + } + //Delete role name that was stored in previous call + oid = tenant + get_names_oid_prefix() + name; + int name_ret = rgw_delete_system_obj(store, pool, oid, NULL); + if (name_ret < 0) { + ldout(cct, 0) << "ERROR: cleanup of role name from pool: " << pool.name << ": " + << name << ": " << cpp_strerror(-name_ret) << dendl; + } + return ret; + } + return 0; +} + +int RGWRole::delete_obj() +{ + auto& pool = store->get_zone_params().roles_pool; + + int ret = read_name(); + if (ret < 0) { + return ret; + } + + ret = read_info(); + if (ret < 0) { + return ret; + } + + if (! perm_policy_map.empty()) { + return -ERR_DELETE_CONFLICT; + } + + // Delete id + string oid = get_info_oid_prefix() + id; + ret = rgw_delete_system_obj(store, pool, oid, NULL); + if (ret < 0) { + ldout(cct, 0) << "ERROR: deleting role id from pool: " << pool.name << ": " + << id << ": " << cpp_strerror(-ret) << dendl; + } + + // Delete name + oid = tenant + get_names_oid_prefix() + name; + ret = rgw_delete_system_obj(store, pool, oid, NULL); + if (ret < 0) { + ldout(cct, 0) << "ERROR: deleting role name from pool: " << pool.name << ": " + << name << ": " << cpp_strerror(-ret) << dendl; + } + + // Delete path + oid = tenant + get_path_oid_prefix() + path + get_info_oid_prefix() + id; + ret = rgw_delete_system_obj(store, pool, oid, NULL); + if (ret < 0) { + ldout(cct, 0) << "ERROR: deleting role path from pool: " << pool.name << ": " + << path << ": " << cpp_strerror(-ret) << dendl; + } + return ret; +} + +int RGWRole::get() +{ + int ret = read_name(); + if (ret < 0) { + return ret; + } + + ret = read_info(); + if (ret < 0) { + return ret; + } + + return 0; +} + +int RGWRole::get_by_id() +{ + int ret = read_info(); + if (ret < 0) { + return ret; + } + + return 0; +} + +int RGWRole::update() +{ + auto& pool = store->get_zone_params().roles_pool; + + int ret = store_info(false); + if (ret < 0) { + ldout(cct, 0) << "ERROR: storing info in pool: " << pool.name << ": " + << id << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + + return 0; +} + +void RGWRole::set_perm_policy(const string& policy_name, const string& perm_policy) +{ + perm_policy_map[policy_name] = perm_policy; +} + +vector RGWRole::get_role_policy_names() +{ + vector policy_names; + for (const auto& it : perm_policy_map) + { + policy_names.push_back(std::move(it.first)); + } + + return policy_names; +} + +int RGWRole::get_role_policy(const string& policy_name, string& perm_policy) +{ + const auto it = perm_policy_map.find(policy_name); + if (it == perm_policy_map.end()) { + ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; + return -EINVAL; + } else { + perm_policy = it->second; + } + return 0; +} + +int RGWRole::delete_policy(const string& policy_name) +{ + const auto& it = perm_policy_map.find(policy_name); + if (it == perm_policy_map.end()) { + ldout(cct, 0) << "ERROR: Policy name: " << policy_name << " not found" << dendl; + return -ENOENT; + } else { + perm_policy_map.erase(it); + } + return 0; +} + +void RGWRole::dump(Formatter *f) const +{ + encode_json("id", id , f); + encode_json("name", name , f); + encode_json("path", path, f); + encode_json("arn", arn, f); + encode_json("create_date", creation_date, f); + encode_json("assume_role_policy_document", trust_policy, f); +} + +void RGWRole::decode_json(JSONObj *obj) +{ + JSONDecoder::decode_json("id", id, obj); + JSONDecoder::decode_json("name", name, obj); + JSONDecoder::decode_json("path", path, obj); + JSONDecoder::decode_json("arn", arn, obj); + JSONDecoder::decode_json("create_date", creation_date, obj); + JSONDecoder::decode_json("assume_role_policy_document", trust_policy, obj); +} + +int RGWRole::read_id(const string& role_name, const string& tenant, string& role_id) +{ + auto& pool = store->get_zone_params().roles_pool; + string oid = tenant + get_names_oid_prefix() + role_name; + bufferlist bl; + RGWObjectCtx obj_ctx(store); + + int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); + if (ret < 0) { + return ret; + } + + RGWNameToId nameToId; + try { + bufferlist::iterator iter = bl.begin(); + ::decode(nameToId, iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: failed to decode role from pool: " << pool.name << ": " + << role_name << dendl; + return -EIO; + } + role_id = nameToId.obj_id; + return 0; +} + +int RGWRole::read_info() +{ + auto& pool = store->get_zone_params().roles_pool; + string oid = get_info_oid_prefix() + id; + bufferlist bl; + RGWObjectCtx obj_ctx(store); + + int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); + if (ret < 0) { + ldout(cct, 0) << "ERROR: failed reading role info from pool: " << pool.name << + ": " << id << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + + try { + bufferlist::iterator iter = bl.begin(); + ::decode(*this, iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: failed to decode role info from pool: " << pool.name << + ": " << id << dendl; + return -EIO; + } + + return 0; +} + +int RGWRole::read_name() +{ + auto& pool = store->get_zone_params().roles_pool; + string oid = tenant + get_names_oid_prefix() + name; + bufferlist bl; + RGWObjectCtx obj_ctx(store); + + int ret = rgw_get_system_obj(store, obj_ctx, pool, oid, bl, NULL, NULL); + if (ret < 0) { + ldout(cct, 0) << "ERROR: failed reading role name from pool: " << pool.name << ": " + << name << ": " << cpp_strerror(-ret) << dendl; + return ret; + } + + RGWNameToId nameToId; + try { + bufferlist::iterator iter = bl.begin(); + ::decode(nameToId, iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: failed to decode role name from pool: " << pool.name << ": " + << name << dendl; + return -EIO; + } + id = nameToId.obj_id; + return 0; +} + +bool RGWRole::validate_input() +{ + if (name.length() > MAX_ROLE_NAME_LEN) { + ldout(cct, 0) << "ERROR: Invalid name length " << dendl; + return false; + } + + if (path.length() > MAX_PATH_NAME_LEN) { + ldout(cct, 0) << "ERROR: Invalid path length " << dendl; + return false; + } + + boost::regex regex_name("[A-Za-z0-9:=,.@-]+"); + if (! boost::regex_match(name, regex_name)) { + ldout(cct, 0) << "ERROR: Invalid chars in name " << dendl; + return false; + } + + boost::regex regex_path("(/[!-~]+/)|(/)"); + if (! boost::regex_match(path,regex_path)) { + ldout(cct, 0) << "ERROR: Invalid chars in path " << dendl; + return false; + } + + return true; +} + +void RGWRole::extract_name_tenant(const std::string& str) +{ + size_t pos = str.find('$'); + if (pos != std::string::npos) { + tenant = str.substr(0, pos); + name = str.substr(pos + 1); + } +} + +void RGWRole::update_trust_policy(string& trust_policy) +{ + this->trust_policy = trust_policy; +} + +int RGWRole::get_roles_by_path_prefix(RGWRados *store, + CephContext *cct, + const string& path_prefix, + const string& tenant, + vector& roles) +{ + auto pool = store->get_zone_params().roles_pool; + string prefix; + + // List all roles if path prefix is empty + if (! path_prefix.empty()) { + prefix = tenant + role_path_oid_prefix + path_prefix; + } else { + prefix = tenant + role_path_oid_prefix; + } + + //Get the filtered objects + list result; + bool is_truncated; + RGWListRawObjsCtx ctx; + do { + list oids; + int r = store->list_raw_objects(pool, prefix, 1000, ctx, oids, &is_truncated); + if (r < 0) { + ldout(cct, 0) << "ERROR: listing filtered objects failed: " << pool.name << ": " + << prefix << ": " << cpp_strerror(-r) << dendl; + return r; + } + for (const auto& iter : oids) { + result.push_back(iter.substr(role_path_oid_prefix.size())); + } + } while (is_truncated); + + for (const auto& it : result) { + //Find the role oid prefix from the end + size_t pos = it.rfind(role_oid_prefix); + if (pos == string::npos) { + continue; + } + // Split the result into path and info_oid + id + string path = it.substr(0, pos); + + /*Make sure that prefix is part of path (False results could've been returned) + because of the role info oid + id appended to the path)*/ + if(path_prefix.empty() || path.find(path_prefix) != string::npos) { + //Get id from info oid prefix + id + string id = it.substr(pos + role_oid_prefix.length()); + + RGWRole role(cct, store); + role.set_id(id); + int ret = role.read_info(); + if (ret < 0) { + return ret; + } + roles.push_back(std::move(role)); + } + } + + return 0; +} + +const string& RGWRole::get_names_oid_prefix() +{ + return role_name_oid_prefix; +} + +const string& RGWRole::get_info_oid_prefix() +{ + return role_oid_prefix; +} + +const string& RGWRole::get_path_oid_prefix() +{ + return role_path_oid_prefix; +}