_add_grant(grant);
}
+void RGWAccessControlList::remove_canon_user_grant(rgw_user& user_id)
+{
+ auto multi_map_iter = grant_map.find(user_id.to_str());
+ if(multi_map_iter != grant_map.end()) {
+ auto grants = grant_map.equal_range(user_id.to_str());
+ grant_map.erase(grants.first, grants.second);
+ }
+
+ auto map_iter = acl_user_map.find(user_id.to_str());
+ if (map_iter != acl_user_map.end()){
+ acl_user_map.erase(map_iter);
+ }
+}
+
uint32_t RGWAccessControlList::get_perm(const DoutPrefixProvider* dpp,
const rgw::auth::Identity& auth_identity,
const uint32_t perm_mask)
static void generate_test_instances(list<RGWAccessControlList*>& o);
void add_grant(ACLGrant *grant);
+ void remove_canon_user_grant(rgw_user& user_id);
multimap<string, ACLGrant>& get_grant_map() { return grant_map; }
const multimap<string, ACLGrant>& get_grant_map() const { return grant_map; }
cout << " bucket stats returns bucket statistics\n";
cout << " bucket rm remove bucket\n";
cout << " bucket check check bucket index\n";
+ cout << " bucket chown link bucket to specified user and update its object ACLs\n";
cout << " bucket reshard reshard bucket\n";
cout << " bucket rewrite rewrite all objects in the specified bucket\n";
cout << " bucket sync disable disable bucket sync\n";
OPT_BUCKET_RM,
OPT_BUCKET_REWRITE,
OPT_BUCKET_RESHARD,
+ OPT_BUCKET_CHOWN,
OPT_POLICY,
OPT_POOL_ADD,
OPT_POOL_RM,
return OPT_BUCKET_STATS;
if (strcmp(cmd, "rm") == 0)
return OPT_BUCKET_RM;
+ if (strcmp(cmd, "chown") == 0)
+ return OPT_BUCKET_CHOWN;
if (strcmp(cmd, "rewrite") == 0)
return OPT_BUCKET_REWRITE;
if (strcmp(cmd, "reshard") == 0)
}
}
+ if (opt_cmd == OPT_BUCKET_CHOWN) {
+
+ bucket_op.set_bucket_name(bucket_name);
+ bucket_op.set_new_bucket_name(new_bucket_name);
+ string err;
+ string marker;
+
+ int r = RGWBucketAdminOp::chown(store, bucket_op, marker, &err);
+ if (r < 0) {
+ cerr << "failure: " << cpp_strerror(-r) << ": " << err << std::endl;
+ return -r;
+ }
+ }
+
if (opt_cmd == OPT_LOG_LIST) {
// filter by date?
if (date.size() && date.size() != 10) {
#include "rgw_user.h"
#include "rgw_string.h"
#include "rgw_multi.h"
+#include "rgw_op.h"
#include "services/svc_zone.h"
#include "services/svc_sys_obj.h"
return 0;
}
+int RGWBucket::chown(RGWBucketAdminOpState& op_state,
+ map<string, bufferlist>& attrs, const string& marker, std::string *err_msg)
+{
+
+ //after bucket link
+ rgw_bucket& bucket = op_state.get_bucket();
+ tenant = bucket.tenant;
+ bucket_name = bucket.name;
+
+ std::vector<rgw_bucket_dir_entry> objs;
+ map<string, bool> common_prefixes;
+ RGWObjectCtx obj_ctx(store);
+
+ RGWBucketInfo bucket_info;
+ RGWSysObjectCtx sys_ctx = store->svc.sysobj->init_obj_ctx();
+
+ int ret = store->get_bucket_info(sys_ctx, tenant, bucket_name, bucket_info, NULL, &attrs);
+ if (ret < 0) {
+ set_err_msg(err_msg, "bucket info failed: tenant: " + tenant + "bucket_name: " + bucket_name + " " + cpp_strerror(-ret));
+ return ret;
+ }
+
+ RGWUserInfo user_info;
+ ret = rgw_get_user_info_by_uid(store, bucket_info.owner, user_info);
+ if (ret < 0) {
+ set_err_msg(err_msg, "user info failed: " + cpp_strerror(-ret));
+ return ret;
+ }
+
+ RGWRados::Bucket target(store, bucket_info);
+ RGWRados::Bucket::List list_op(&target);
+
+ list_op.params.list_versions = true;
+ list_op.params.allow_unordered = true;
+ list_op.params.marker = marker;
+
+ bool is_truncated = false;
+ int count = 0;
+ int max_entries = 1000;
+
+ //Loop through objects and update object acls to point to bucket owner
+
+ do {
+ objs.clear();
+ ret = list_op.list_objects(max_entries, &objs, &common_prefixes, &is_truncated);
+ if (ret < 0) {
+ set_err_msg(err_msg, "list objects failed: " + cpp_strerror(-ret));
+ return ret;
+ }
+
+ list_op.params.marker = list_op.get_next_marker();
+ count += objs.size();
+
+ for (const auto& obj : objs) {
+
+ const rgw_obj r_obj(bucket_info.bucket, obj.key);
+ ret = get_obj_attrs(store, obj_ctx, bucket_info, r_obj, attrs);
+ if (ret < 0){
+ set_err_msg(err_msg, "failed to read object " + obj.key.name + "with " + cpp_strerror(-ret));
+ continue;
+ }
+ const auto& aiter = attrs.find(RGW_ATTR_ACL);
+ if (aiter == attrs.end()) {
+ set_err_msg(err_msg, "no acls found for object " + obj.key.name + " .Continuing with next object." + cpp_strerror(-ret));
+ continue;
+ } else {
+ bufferlist& bl = aiter->second;
+ RGWAccessControlPolicy policy(store->ctx());
+ ACLOwner owner;
+ try {
+ decode(policy, bl);
+ owner = policy.get_owner();
+ } catch (buffer::error& err) {
+ set_err_msg(err_msg, "decode policy failed: ");
+ return -EIO;
+ }
+
+ //Get the ACL from the policy
+ RGWAccessControlList& acl = policy.get_acl();
+
+ //Remove grant that is set to old owner
+ acl.remove_canon_user_grant(owner.get_id());
+
+ //Create a grant and add grant
+ ACLGrant grant;
+ grant.set_canon(bucket_info.owner, user_info.display_name, RGW_PERM_FULL_CONTROL);
+ acl.add_grant(&grant);
+
+ //Update the ACL owner to the new user
+ owner.set_id(bucket_info.owner);
+ owner.set_name(user_info.display_name);
+ policy.set_owner(owner);
+
+ bl.clear();
+ encode(policy, bl);
+
+ ret = modify_obj_attr(store, obj_ctx, bucket_info, r_obj, RGW_ATTR_ACL, bl);
+ if (ret < 0) {
+ set_err_msg(err_msg, "modify attr failed: " + cpp_strerror(-ret));
+ return ret;
+ }
+ }
+ } cerr << count << " objects processed, next marker " << list_op.params.marker.name << std::endl;
+ } while(is_truncated);
+ return 0;
+}
+
int RGWBucket::unlink(RGWBucketAdminOpState& op_state, std::string *err_msg)
{
rgw_bucket bucket = op_state.get_bucket();
}
+int RGWBucketAdminOp::chown(RGWRados *store, RGWBucketAdminOpState& op_state, const string& marker, string *err)
+{
+ RGWBucket bucket;
+ map<string, bufferlist> attrs;
+
+ int ret = bucket.init(store, op_state, err, &attrs);
+ if (ret < 0)
+ return ret;
+
+ ret = bucket.link(op_state, attrs, err);
+ if (ret < 0)
+ return ret;
+
+ return bucket.chown(op_state, attrs, marker, err);
+
+}
+
int RGWBucketAdminOp::check_index(RGWRados *store, RGWBucketAdminOpState& op_state,
RGWFormatterFlusher& flusher, optional_yield y)
{
int remove(RGWBucketAdminOpState& op_state, optional_yield y, bool bypass_gc = false, bool keep_index_consistent = true, std::string *err_msg = NULL);
int link(RGWBucketAdminOpState& op_state, map<string, bufferlist>& attrs,
std::string *err_msg = NULL);
+ int chown(RGWBucketAdminOpState& op_state, map<string, bufferlist>& attrs, const string& marker, std::string *err_msg = NULL);
int unlink(RGWBucketAdminOpState& op_state, std::string *err_msg = NULL);
int set_quota(RGWBucketAdminOpState& op_state, std::string *err_msg = NULL);
static int unlink(RGWRados *store, RGWBucketAdminOpState& op_state);
static int link(RGWRados *store, RGWBucketAdminOpState& op_state, string *err_msg = NULL);
+ static int chown(RGWRados *store, RGWBucketAdminOpState& op_state, const string& marker, string *err_msg = NULL);
static int check_index(RGWRados *store, RGWBucketAdminOpState& op_state,
RGWFormatterFlusher& flusher, optional_yield y);
return policies;
}
-static int get_obj_attrs(RGWRados *store, struct req_state *s, const rgw_obj& obj, map<string, bufferlist>& attrs)
+int get_obj_attrs(RGWRados *store, RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& obj, map<string, bufferlist>& attrs)
{
- RGWRados::Object op_target(store, s->bucket_info, *static_cast<RGWObjectCtx *>(s->obj_ctx), obj);
+ RGWRados::Object op_target(store, bucket_info, obj_ctx, obj);
RGWRados::Object::Read read_op(&op_target);
read_op.params.attrs = &attrs;
return get_multipart_info(store, s, meta_obj, policy, attrs, upload_info);
}
-static int modify_obj_attr(RGWRados *store, struct req_state *s, const rgw_obj& obj, const char* attr_name, bufferlist& attr_val)
+int modify_obj_attr(RGWRados *store, RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& obj, const char* attr_name, bufferlist& attr_val)
{
map<string, bufferlist> attrs;
- RGWRados::Object op_target(store, s->bucket_info, *static_cast<RGWObjectCtx *>(s->obj_ctx), obj);
+ RGWRados::Object op_target(store, bucket_info, obj_ctx, obj);
RGWRados::Object::Read read_op(&op_target);
read_op.params.attrs = &attrs;
-
+
int r = read_op.prepare(s->yield);
if (r < 0) {
return r;
static int rgw_iam_add_existing_objtags(RGWRados* store, struct req_state* s, rgw_obj& obj, std::uint64_t action){
map <string, bufferlist> attrs;
store->set_atomic(s->obj_ctx, obj);
- int op_ret = get_obj_attrs(store, s, obj, attrs);
+ int op_ret = get_obj_attrs(store, *(s->obj_ctx), s->bucket_info, obj, attrs);
if (op_ret < 0)
return op_ret;
auto tags = attrs.find(RGW_ATTR_TAGS);
store->set_atomic(s->obj_ctx, obj);
- op_ret = get_obj_attrs(store, s, obj, attrs);
+ op_ret = get_obj_attrs(store, *(s->obj_ctx), s->bucket_info, obj, attrs);
if (op_ret < 0) {
ldpp_dout(this, 0) << "ERROR: failed to get obj attrs, obj=" << obj
<< " ret=" << op_ret << dendl;
rgw_obj obj;
obj = rgw_obj(s->bucket, s->object);
store->set_atomic(s->obj_ctx, obj);
- op_ret = modify_obj_attr(store, s, obj, RGW_ATTR_TAGS, tags_bl);
+ op_ret = modify_obj_attr(store, *(s->obj_ctx), s->bucket_info, obj, RGW_ATTR_TAGS, tags_bl);
if (op_ret == -ECANCELED){
op_ret = -ERR_TAG_CONFLICT;
}
}
/* check if obj exists, read orig attrs */
- op_ret = get_obj_attrs(store, s, obj, orig_attrs);
+ op_ret = get_obj_attrs(store, *(s->obj_ctx), s->bucket_info, obj, orig_attrs);
if (op_ret < 0) {
return;
}
if (!s->object.empty()) {
if (need_object_expiration() || multipart_delete) {
/* check if obj exists, read orig attrs */
- op_ret = get_obj_attrs(store, s, obj, attrs);
+ op_ret = get_obj_attrs(store, *(s->obj_ctx), s->bucket_info, obj, attrs);
if (op_ret < 0) {
return;
}
obj = rgw_obj(s->bucket, s->object);
store->set_atomic(s->obj_ctx, obj);
//if instance is empty, we should modify the latest object
- op_ret = modify_obj_attr(store, s, obj, RGW_ATTR_ACL, bl);
+ op_ret = modify_obj_attr(store, *(s->obj_ctx), s->bucket_info, obj, RGW_ATTR_ACL, bl);
} else {
attrs = s->bucket_attrs;
attrs[RGW_ATTR_ACL] = bl;
return;
}
- op_ret = get_obj_attrs(store, s, meta_obj, attrs);
+ op_ret = get_obj_attrs(store, *(s->obj_ctx), s->bucket_info, meta_obj, attrs);
if (op_ret < 0) {
ldpp_dout(this, 0) << "ERROR: failed to get obj attrs, obj=" << meta_obj
return 0;
}
+int get_obj_attrs(RGWRados *store, RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& obj, map<string, bufferlist>& attrs);
+int modify_obj_attr(RGWRados *store, RGWObjectCtx& obj_ctx, RGWBucketInfo& bucket_info, const rgw_obj& obj, const char* attr_name, bufferlist& attr_val);
#endif /* CEPH_RGW_OP_H */
bucket stats returns bucket statistics
bucket rm remove bucket
bucket check check bucket index
+ bucket chown link bucket to specified user and update its object ACLs
bucket reshard reshard bucket
bucket rewrite rewrite all objects in the specified bucket
bucket sync disable disable bucket sync