From a4550801cbfdff55ad5f00865462d4ce30d2b139 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Fri, 22 Nov 2019 21:02:36 -0800 Subject: [PATCH] rgw: data sync: check user permission in user level sync Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_admin.cc | 5 +- src/rgw/rgw_bucket_sync.cc | 11 +- src/rgw/rgw_bucket_sync.h | 11 +- src/rgw/rgw_common.h | 7 + src/rgw/rgw_cr_rados.cc | 5 +- src/rgw/rgw_cr_rados.h | 10 +- src/rgw/rgw_data_sync.cc | 360 ++++++++++++++++++----- src/rgw/rgw_data_sync.h | 2 + src/rgw/rgw_trim_bilog.cc | 2 +- src/rgw/services/svc_bucket_sync_sobj.cc | 5 +- 10 files changed, 337 insertions(+), 81 deletions(-) diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index acfd7974152..509a0ed5ac2 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -2397,15 +2397,16 @@ static int sync_info(std::optional opt_target_zone, std::optional bucket_attrs; - int ret = init_bucket(*eff_bucket, bucket_info, bucket); + int ret = init_bucket(*eff_bucket, bucket_info, bucket, &bucket_attrs); if (ret < 0 && ret != -ENOENT) { cerr << "ERROR: init_bucket failed: " << cpp_strerror(-ret) << std::endl; return ret; } if (ret >= 0) { - bucket_handler.reset(handler->alloc_child(bucket_info)); + bucket_handler.reset(handler->alloc_child(bucket_info, std::move(bucket_attrs))); } else { cerr << "WARNING: bucket not found, simulating result" << std::endl; bucket_handler.reset(handler->alloc_child(*eff_bucket, nullopt)); diff --git a/src/rgw/rgw_bucket_sync.cc b/src/rgw/rgw_bucket_sync.cc index 3a57f546a73..6ce7341b417 100644 --- a/src/rgw/rgw_bucket_sync.cc +++ b/src/rgw/rgw_bucket_sync.cc @@ -669,8 +669,10 @@ RGWBucketSyncPolicyHandler::RGWBucketSyncPolicyHandler(RGWSI_Zone *_zone_svc, } RGWBucketSyncPolicyHandler::RGWBucketSyncPolicyHandler(const RGWBucketSyncPolicyHandler *_parent, - const RGWBucketInfo& _bucket_info) : parent(_parent), - bucket_info(_bucket_info) { + const RGWBucketInfo& _bucket_info, + map&& _bucket_attrs) : parent(_parent), + bucket_info(_bucket_info), + bucket_attrs(std::move(_bucket_attrs)) { if (_bucket_info.sync_policy) { sync_policy = *_bucket_info.sync_policy; @@ -705,9 +707,10 @@ RGWBucketSyncPolicyHandler::RGWBucketSyncPolicyHandler(const RGWBucketSyncPolicy parent->flow_mgr.get())); } -RGWBucketSyncPolicyHandler *RGWBucketSyncPolicyHandler::alloc_child(const RGWBucketInfo& bucket_info) const +RGWBucketSyncPolicyHandler *RGWBucketSyncPolicyHandler::alloc_child(const RGWBucketInfo& bucket_info, + map&& bucket_attrs) const { - return new RGWBucketSyncPolicyHandler(this, bucket_info); + return new RGWBucketSyncPolicyHandler(this, bucket_info, std::move(bucket_attrs)); } RGWBucketSyncPolicyHandler *RGWBucketSyncPolicyHandler::alloc_child(const rgw_bucket& bucket, diff --git a/src/rgw/rgw_bucket_sync.h b/src/rgw/rgw_bucket_sync.h index a57c461de85..8545d4986d5 100644 --- a/src/rgw/rgw_bucket_sync.h +++ b/src/rgw/rgw_bucket_sync.h @@ -280,6 +280,7 @@ class RGWBucketSyncPolicyHandler { RGWSI_Bucket_Sync *bucket_sync_svc; rgw_zone_id zone_id; std::optional bucket_info; + std::optional > bucket_attrs; std::optional bucket; std::unique_ptr flow_mgr; rgw_sync_policy_info sync_policy; @@ -308,7 +309,8 @@ class RGWBucketSyncPolicyHandler { } RGWBucketSyncPolicyHandler(const RGWBucketSyncPolicyHandler *_parent, - const RGWBucketInfo& _bucket_info); + const RGWBucketInfo& _bucket_info, + map&& _bucket_attrs); RGWBucketSyncPolicyHandler(const RGWBucketSyncPolicyHandler *_parent, const rgw_bucket& _bucket, @@ -319,7 +321,8 @@ public: RGWSI_Bucket_Sync *bucket_sync_svc, std::optional effective_zone = std::nullopt); - RGWBucketSyncPolicyHandler *alloc_child(const RGWBucketInfo& bucket_info) const; + RGWBucketSyncPolicyHandler *alloc_child(const RGWBucketInfo& bucket_info, + map&& bucket_attrs) const; RGWBucketSyncPolicyHandler *alloc_child(const rgw_bucket& bucket, std::optional sync_policy) const; @@ -367,6 +370,10 @@ public: return bucket_info; } + const std::optional >& get_bucket_attrs() const { + return bucket_attrs; + } + void get_pipes(RGWBucketSyncFlowManager::pipe_set **_sources, RGWBucketSyncFlowManager::pipe_set **_targets) { /* return raw pipes (with zone name) */ *_sources = &source_pipes; *_targets = &target_pipes; diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index d11f6a81acf..497af6bc8ae 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -2496,6 +2496,13 @@ bool verify_user_permission_no_policy(const DoutPrefixProvider* dpp, RGWAccessControlPolicy * const user_acl, const int perm); +bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, + struct perm_state_base * const s, + RGWAccessControlPolicy * const user_acl, + RGWAccessControlPolicy * const bucket_acl, + RGWAccessControlPolicy * const object_acl, + const int perm); + /** Check if the req_state's user has the necessary permissions * to do the requested action */ rgw::IAM::Effect eval_user_policies(const vector& user_policies, diff --git a/src/rgw/rgw_cr_rados.cc b/src/rgw/rgw_cr_rados.cc index 93748ef2456..b1da90104cf 100644 --- a/src/rgw/rgw_cr_rados.cc +++ b/src/rgw/rgw_cr_rados.cc @@ -533,9 +533,10 @@ int RGWAsyncGetBucketInstanceInfo::_send_request() int r; if (!bucket.bucket_id.empty()) { RGWSysObjectCtx obj_ctx = store->svc()->sysobj->init_obj_ctx(); - r = store->getRados()->get_bucket_instance_info(obj_ctx, bucket, bucket_info, nullptr, nullptr, null_yield); + r = store->getRados()->get_bucket_instance_info(obj_ctx, bucket, bucket_info, nullptr, &attrs, null_yield); } else { - r = store->ctl()->bucket->read_bucket_info(bucket, &bucket_info, null_yield); + r = store->ctl()->bucket->read_bucket_info(bucket, &bucket_info, null_yield, + RGWBucketCtl::BucketInstance::GetParams().set_attrs(&attrs)); } if (r < 0) { ldout(store->ctx(), 0) << "ERROR: failed to get bucket instance info for " diff --git a/src/rgw/rgw_cr_rados.h b/src/rgw/rgw_cr_rados.h index 289ff546486..36752997eb4 100644 --- a/src/rgw/rgw_cr_rados.h +++ b/src/rgw/rgw_cr_rados.h @@ -863,6 +863,7 @@ public: : RGWAsyncRadosRequest(caller, cn), store(_store), bucket(bucket) {} RGWBucketInfo bucket_info; + map attrs; }; class RGWGetBucketInstanceInfoCR : public RGWSimpleCoroutine { @@ -870,15 +871,17 @@ class RGWGetBucketInstanceInfoCR : public RGWSimpleCoroutine { rgw::sal::RGWRadosStore *store; rgw_bucket bucket; RGWBucketInfo *bucket_info; + map *pattrs; RGWAsyncGetBucketInstanceInfo *req{nullptr}; public: // rgw_bucket constructor RGWGetBucketInstanceInfoCR(RGWAsyncRadosProcessor *_async_rados, rgw::sal::RGWRadosStore *_store, - const rgw_bucket& _bucket, RGWBucketInfo *_bucket_info) + const rgw_bucket& _bucket, RGWBucketInfo *_bucket_info, + map *_pattrs) : RGWSimpleCoroutine(_store->ctx()), async_rados(_async_rados), store(_store), - bucket(_bucket), bucket_info(_bucket_info) {} + bucket(_bucket), bucket_info(_bucket_info), pattrs(_pattrs) {} ~RGWGetBucketInstanceInfoCR() override { request_cleanup(); } @@ -898,6 +901,9 @@ public: if (bucket_info) { *bucket_info = std::move(req->bucket_info); } + if (pattrs) { + *pattrs = std::move(req->attrs); + } return req->get_ret_status(); } }; diff --git a/src/rgw/rgw_data_sync.cc b/src/rgw/rgw_data_sync.cc index 101b6199741..11fb88f561c 100644 --- a/src/rgw/rgw_data_sync.cc +++ b/src/rgw/rgw_data_sync.cc @@ -1047,10 +1047,16 @@ public: int operate() override; }; +struct all_bucket_info { + RGWBucketInfo bucket_info; + map attrs; +}; + struct rgw_sync_pipe_info_entity { private: RGWBucketInfo bucket_info; + map bucket_attrs; bool _has_bucket_info{false}; public: @@ -1058,7 +1064,7 @@ public: rgw_sync_pipe_info_entity() {} rgw_sync_pipe_info_entity(const rgw_sync_bucket_entity& e, - std::optional& binfo) { + std::optional& binfo) { if (e.zone) { zone = *e.zone; } @@ -1066,14 +1072,14 @@ public: return; } if (!binfo || - binfo->bucket != *e.bucket) { + binfo->bucket_info.bucket != *e.bucket) { bucket_info.bucket = *e.bucket; } else { set_bucket_info(*binfo); } } - void update_empty_bucket_info(const std::map& buckets_info) { + void update_empty_bucket_info(const std::map& buckets_info) { if (_has_bucket_info) { return; } @@ -1093,8 +1099,9 @@ public: return _has_bucket_info; } - void set_bucket_info(const RGWBucketInfo& _bucket_info) { - bucket_info = _bucket_info; + void set_bucket_info(const all_bucket_info& all_info) { + bucket_info = all_info.bucket_info; + bucket_attrs = all_info.attrs; _has_bucket_info = true; } @@ -1131,10 +1138,10 @@ struct rgw_sync_pipe_handler_info { rgw_sync_pipe_handler_info() {} rgw_sync_pipe_handler_info(const RGWBucketSyncFlowManager::pipe_handler& _handler, - std::optional source_bucket_info, - std::optional target_bucket_info) : handler(_handler), - source(handler.source, source_bucket_info), - target(handler.dest, target_bucket_info) { + std::optional source_bucket_info, + std::optional target_bucket_info) : handler(_handler), + source(handler.source, source_bucket_info), + target(handler.dest, target_bucket_info) { } bool operator<(const rgw_sync_pipe_handler_info& p) const { @@ -1147,7 +1154,7 @@ struct rgw_sync_pipe_handler_info { return (target < p.target); } - void update_empty_bucket_info(const std::map& buckets_info) { + void update_empty_bucket_info(const std::map& buckets_info) { source.update_empty_bucket_info(buckets_info); target.update_empty_bucket_info(buckets_info); } @@ -1168,8 +1175,8 @@ struct rgw_sync_pipe_info_set { } void insert(const RGWBucketSyncFlowManager::pipe_handler& handler, - std::optional& source_bucket_info, - std::optional& target_bucket_info) { + std::optional& source_bucket_info, + std::optional& target_bucket_info) { rgw_sync_pipe_handler_info p(handler, source_bucket_info, target_bucket_info); handlers.insert(p); } @@ -1186,7 +1193,7 @@ struct rgw_sync_pipe_info_set { return handlers.empty(); } - void update_empty_bucket_info(const std::map& buckets_info) { + void update_empty_bucket_info(const std::map& buckets_info) { if (buckets_info.empty()) { return; } @@ -1971,16 +1978,188 @@ int RGWDefaultSyncModule::create_instance(CephContext *cct, const JSONFormattabl return 0; } +class RGWUserPermHandler { + friend struct Init; + friend class Bucket; + + RGWDataSyncEnv *sync_env; + rgw_user uid; + + struct _info { + RGWUserInfo user_info; + rgw::IAM::Environment env; + std::unique_ptr identity; + RGWAccessControlPolicy user_acl; + }; + + std::shared_ptr<_info> info; + + struct Init; + + std::shared_ptr init_action; + + struct Init : public RGWGenericAsyncCR::Action { + RGWDataSyncEnv *sync_env; + + rgw_user uid; + std::shared_ptr info; + + int ret{0}; + + Init(RGWUserPermHandler *handler) : sync_env(handler->sync_env), + uid(handler->uid), + info(handler->info) {} + int operate() override { + auto user_ctl = sync_env->store->getRados()->ctl.user; + + ret = user_ctl->get_info_by_uid(uid, &info->user_info, null_yield); + if (ret < 0) { + return ret; + } + + info->identity = rgw::auth::transform_old_authinfo(sync_env->cct, + uid, + RGW_PERM_FULL_CONTROL, + false, /* system_request? */ + TYPE_RGW); + + map uattrs; + + ret = user_ctl->get_attrs_by_uid(uid, &uattrs, null_yield); + if (ret == 0) { + ret = RGWUserPermHandler::policy_from_attrs(sync_env->cct, uattrs, &info->user_acl); + } + if (ret == -ENOENT) { + info->user_acl.create_default(uid, info->user_info.display_name); + } + + return 0; + } + }; + +public: + RGWUserPermHandler(RGWDataSyncEnv *_sync_env, + const rgw_user& _uid) : sync_env(_sync_env), + uid(_uid) {} + + RGWCoroutine *init_cr() { + info = make_shared<_info>(); + init_action = make_shared(this); + + return new RGWGenericAsyncCR(sync_env->cct, + sync_env->async_rados, + init_action); + } + + class Bucket { + RGWDataSyncEnv *sync_env; + std::shared_ptr<_info> info; + RGWAccessControlPolicy bucket_acl; + std::optional ps; + public: + Bucket() {} + + int init(RGWUserPermHandler *handler, + const RGWBucketInfo& bucket_info, + const map& bucket_attrs); + + bool verify_bucket_permission(int perm); + bool verify_object_permission(const map& obj_attrs, + int perm); + }; + + static int policy_from_attrs(CephContext *cct, + const map& attrs, + RGWAccessControlPolicy *acl) { + acl->set_ctx(cct); + + auto aiter = attrs.find(RGW_ATTR_ACL); + if (aiter == attrs.end()) { + return -ENOENT; + } + auto iter = aiter->second.begin(); + try { + acl->decode(iter); + } catch (buffer::error& err) { + ldout(cct, 0) << "ERROR: " << __func__ << "(): could not decode policy, caught buffer::error" << dendl; + return -EIO; + } + + return 0; + } + + int init_bucket(const RGWBucketInfo& bucket_info, + const map& bucket_attrs, + Bucket *bs) { + return bs->init(this, bucket_info, bucket_attrs); + } +}; + +int RGWUserPermHandler::Bucket::init(RGWUserPermHandler *handler, + const RGWBucketInfo& bucket_info, + const map& bucket_attrs) +{ + sync_env = handler->sync_env; + info = handler->info; + + int r = RGWUserPermHandler::policy_from_attrs(sync_env->cct, bucket_attrs, &bucket_acl); + if (r < 0) { + return r; + } + + ps.emplace(sync_env->cct, + info->env, + info->identity.get(), + bucket_info, + info->identity->get_perm_mask(), + false, /* defer to bucket acls */ + nullptr, /* referer */ + false); /* request_payer */ + + return 0; +} + +bool RGWUserPermHandler::Bucket::verify_bucket_permission(int perm) +{ + return verify_bucket_permission_no_policy(sync_env->dpp, + &(*ps), + &info->user_acl, + &bucket_acl, + perm); +} + +bool RGWUserPermHandler::Bucket::verify_object_permission(const map& obj_attrs, + int perm) +{ + RGWAccessControlPolicy obj_acl; + + int r = policy_from_attrs(sync_env->cct, obj_attrs, &obj_acl); + if (r < 0) { + return r; + } + + return verify_bucket_permission_no_policy(sync_env->dpp, + &(*ps), + &bucket_acl, + &obj_acl, + perm); +} + class RGWFetchObjFilter_Sync : public RGWFetchObjFilter_Default { rgw_bucket_sync_pipe sync_pipe; + std::shared_ptr bucket_perms; + std::optional mtime; std::optional etag; std::optional obj_size; + std::unique_ptr identity; + public: - RGWFetchObjFilter_Sync(rgw_bucket_sync_pipe& _sync_pipe) : sync_pipe(_sync_pipe) { - } + RGWFetchObjFilter_Sync(rgw_bucket_sync_pipe& _sync_pipe, + std::shared_ptr& _bucket_perms) : sync_pipe(_sync_pipe), + bucket_perms(_bucket_perms) {} int filter(CephContext *cct, const rgw_obj_key& source_key, @@ -2022,22 +2201,10 @@ int RGWFetchObjFilter_Sync::filter(CephContext *cct, std::optional > new_attrs; if (params.mode == rgw_sync_pipe_params::MODE_USER) { -#if 0 - RGWAccessControlPolicy policy; - auto iter = obj_attrs.find(RGW_ATTR_ACL); - if (iter == obj_attrs.end()) { - ldout(cct, 0) << "ERROR: " << __func__ << ": No policy header to object: aborting sync" << dendl; - return abort_err; - } - try { - auto it = iter->second.cbegin(); - decode(policy, it); - } catch (buffer::error &err) { - ldout(cct, 0) << "ERROR: " << __func__ << ": caught buffer::error couldn't decode policy " << dendl; - return abort_err; + if (!bucket_perms->verify_object_permission(obj_attrs, RGW_PERM_READ)) { + ldout(cct, 0) << "ERROR: " << __func__ << ": permission check failed: user not allowed to fetch object" << dendl; + return -EPERM; } -#endif - } if (!dest_placement_rule && @@ -2056,12 +2223,12 @@ int RGWFetchObjFilter_Sync::filter(CephContext *cct, prule); } - class RGWObjFetchCR : public RGWCoroutine { RGWDataSyncCtx *sc; RGWDataSyncEnv *sync_env; rgw_bucket_sync_pipe& sync_pipe; rgw_obj_key& key; + std::optional dest_key; std::optional versioned_epoch; rgw_zone_set *zones_trace; @@ -2078,15 +2245,21 @@ class RGWObjFetchCR : public RGWCoroutine { std::optional param_acl_translation; std::optional param_storage_class; rgw_sync_pipe_params::Mode param_mode; + + std::optional user_perms; + std::shared_ptr source_bucket_perms; + RGWUserPermHandler::Bucket dest_bucket_perms; public: RGWObjFetchCR(RGWDataSyncCtx *_sc, rgw_bucket_sync_pipe& _sync_pipe, rgw_obj_key& _key, + std::optional _dest_key, std::optional _versioned_epoch, rgw_zone_set *_zones_trace) : RGWCoroutine(_sc->cct), sc(_sc), sync_env(_sc->env), sync_pipe(_sync_pipe), key(_key), + dest_key(_dest_key), versioned_epoch(_versioned_epoch), zones_trace(_zones_trace) {} @@ -2154,19 +2327,54 @@ public: param_mode = params.mode; } - yield { - auto filter = make_shared(sync_pipe); + if (param_mode == rgw_sync_pipe_params::MODE_USER) { + if (!param_user) { + ldout(cct, 20) << "ERROR: " << __func__ << ": user level sync but user param not set" << dendl; + return set_cr_error(-EPERM); + } + user_perms.emplace(sync_env, *param_user); - std::optional uid; - if (param_mode == rgw_sync_pipe_params::MODE_USER) { - uid = param_user; + yield call(user_perms->init_cr()); + if (retcode < 0) { + ldout(cct, 20) << "ERROR: " << __func__ << ": failed to init user perms manager for uid=" << *param_user << dendl; + return set_cr_error(retcode); + } + + /* verify that user is allowed to write at the target bucket */ + int r = user_perms->init_bucket(sync_pipe.dest_bucket_info, + sync_pipe.dest_bucket_attrs, + &dest_bucket_perms); + if (r < 0) { + ldout(cct, 20) << "ERROR: " << __func__ << ": failed to init bucket perms manager for uid=" << *param_user << " bucket=" << sync_pipe.source_bucket_info.bucket.get_key() << dendl; + return set_cr_error(retcode); + } + + if (!dest_bucket_perms.verify_bucket_permission(RGW_PERM_WRITE)) { + ldout(cct, 0) << "ERROR: " << __func__ << ": permission check failed: user not allowed to write into bucket (bucket=" << sync_pipe.info.dest_bs.bucket.get_key() << ")" << dendl; + return -EPERM; } + + /* init source bucket permission structure */ + source_bucket_perms = make_shared(); + r = user_perms->init_bucket(sync_pipe.source_bucket_info, + sync_pipe.source_bucket_attrs, + source_bucket_perms.get()); + if (r < 0) { + ldout(cct, 20) << "ERROR: " << __func__ << ": failed to init bucket perms manager for uid=" << *param_user << " bucket=" << sync_pipe.source_bucket_info.bucket.get_key() << dendl; + return set_cr_error(retcode); + } + } + + yield { + + auto filter = make_shared(sync_pipe, source_bucket_perms); + #warning FIXME: race guard call(new RGWFetchRemoteObjCR(sync_env->async_rados, sync_env->store, sc->source_zone, - uid, + param_user, sync_pipe.info.source_bs.bucket, std::nullopt, sync_pipe.dest_bucket_info, - key, std::nullopt, versioned_epoch, + key, dest_key, versioned_epoch, true, std::static_pointer_cast(filter), zones_trace, sync_env->counters, sync_env->dpp)); @@ -2185,9 +2393,7 @@ RGWCoroutine *RGWDefaultDataSyncModule::sync_object(RGWDataSyncCtx *sc, rgw_buck { auto sync_env = sc->env; - auto filter = make_shared(sync_pipe); - - return new RGWObjFetchCR(sc, sync_pipe, key, versioned_epoch, zones_trace); + return new RGWObjFetchCR(sc, sync_pipe, key, std::nullopt, versioned_epoch, zones_trace); } RGWCoroutine *RGWDefaultDataSyncModule::remove_object(RGWDataSyncCtx *sc, rgw_bucket_sync_pipe& sync_pipe, rgw_obj_key& key, @@ -2264,14 +2470,7 @@ RGWCoroutine *RGWArchiveDataSyncModule::sync_object(RGWDataSyncCtx *sc, rgw_buck } } - auto filter = make_shared(sync_pipe); - - return new RGWFetchRemoteObjCR(sync_env->async_rados, sync_env->store, sc->source_zone, nullopt, - sync_pipe.info.source_bs.bucket, std::nullopt, sync_pipe.dest_bucket_info, - key, dest_key, versioned_epoch, - true, - std::static_pointer_cast(filter), - zones_trace, nullptr, sync_env->dpp); + return new RGWObjFetchCR(sc, sync_pipe, key, dest_key, versioned_epoch, zones_trace); } RGWCoroutine *RGWArchiveDataSyncModule::remove_object(RGWDataSyncCtx *sc, rgw_bucket_sync_pipe& sync_pipe, rgw_obj_key& key, @@ -3190,6 +3389,17 @@ public: } }; +static bool ignore_sync_error(int err) { + switch (err) { + case -ENOENT: + case -EPERM: + return true; + default: + break; + } + return false; +} + template class RGWBucketSyncSingleEntryCR : public RGWCoroutine { RGWDataSyncCtx *sc; @@ -3314,8 +3524,10 @@ public: set_status() << "failed to sync obj; retcode=" << retcode; tn->log(0, SSTR("ERROR: failed to sync object: " << bucket_shard_str{bs} << "/" << key.name)); - error_ss << bucket_shard_str{bs} << "/" << key.name; - sync_status = retcode; + if (!ignore_sync_error(retcode)) { + error_ss << bucket_shard_str{bs} << "/" << key.name; + sync_status = retcode; + } } if (!error_ss.str().empty()) { yield call(sync_env->error_logger->log_error_cr(sc->conn->get_remote_id(), "data", error_ss.str(), -retcode, string("failed to sync object") + cpp_strerror(-sync_status))); @@ -3853,10 +4065,10 @@ class RGWGetBucketPeersCR : public RGWCoroutine { std::optional source_bucket; rgw_sync_pipe_info_set *pipes; - map buckets_info; - map::iterator siiter; - std::optional target_bucket_info; - std::optional source_bucket_info; + map buckets_info; + map::iterator siiter; + std::optional target_bucket_info; + std::optional source_bucket_info; rgw_sync_pipe_info_set::iterator siter; @@ -4086,6 +4298,7 @@ class RGWSyncGetBucketInfoCR : public RGWCoroutine { RGWDataSyncEnv *sync_env; rgw_bucket bucket; RGWBucketInfo *pbucket_info; + map *pattrs; RGWMetaSyncEnv meta_sync_env; RGWSyncTraceNodeRef tn; @@ -4094,11 +4307,13 @@ public: RGWSyncGetBucketInfoCR(RGWDataSyncEnv *_sync_env, const rgw_bucket& _bucket, RGWBucketInfo *_pbucket_info, + map *_pattrs, const RGWSyncTraceNodeRef& _tn_parent) : RGWCoroutine(_sync_env->cct), sync_env(_sync_env), bucket(_bucket), pbucket_info(_pbucket_info), + pattrs(_pattrs), tn(sync_env->sync_tracer->add_node(_tn_parent, "get_bucket_info", SSTR(bucket))) { } @@ -4109,7 +4324,7 @@ public: int RGWSyncGetBucketInfoCR::operate() { reenter(this) { - yield call(new RGWGetBucketInstanceInfoCR(sync_env->async_rados, sync_env->store, bucket, pbucket_info)); + yield call(new RGWGetBucketInstanceInfoCR(sync_env->async_rados, sync_env->store, bucket, pbucket_info, pattrs)); if (retcode == -ENOENT) { /* bucket instance info has not been synced in yet, fetch it now */ yield { @@ -4130,7 +4345,7 @@ int RGWSyncGetBucketInfoCR::operate() return set_cr_error(retcode); } - yield call(new RGWGetBucketInstanceInfoCR(sync_env->async_rados, sync_env->store, bucket, pbucket_info)); + yield call(new RGWGetBucketInstanceInfoCR(sync_env->async_rados, sync_env->store, bucket, pbucket_info, pattrs)); } if (retcode < 0) { tn->log(0, SSTR("ERROR: failed to retrieve bucket info for bucket=" << bucket_str{bucket})); @@ -4160,10 +4375,10 @@ void RGWGetBucketPeersCR::update_from_target_bucket_policy() for (siter = pipes->begin(); siter != pipes->end(); ++siter) { if (!siter->source.has_bucket_info()) { - buckets_info.emplace(siter->source.get_bucket(), RGWBucketInfo()); + buckets_info.emplace(siter->source.get_bucket(), all_bucket_info()); } if (!siter->target.has_bucket_info()) { - buckets_info.emplace(siter->target.get_bucket(), RGWBucketInfo()); + buckets_info.emplace(siter->target.get_bucket(), all_bucket_info()); } } } @@ -4185,10 +4400,10 @@ void RGWGetBucketPeersCR::update_from_source_bucket_policy() for (siter = pipes->begin(); siter != pipes->end(); ++siter) { if (!siter->source.has_bucket_info()) { - buckets_info.emplace(siter->source.get_bucket(), RGWBucketInfo()); + buckets_info.emplace(siter->source.get_bucket(), all_bucket_info()); } if (!siter->target.has_bucket_info()) { - buckets_info.emplace(siter->target.get_bucket(), RGWBucketInfo()); + buckets_info.emplace(siter->target.get_bucket(), all_bucket_info()); } } } @@ -4228,7 +4443,15 @@ int RGWGetBucketPeersCR::operate() return set_cr_error(retcode); } - source_bucket_info = source_policy->policy_handler->get_bucket_info(); + if (source_policy->policy_handler) { + auto& opt_bucket_info = source_policy->policy_handler->get_bucket_info(); + auto& opt_attrs = source_policy->policy_handler->get_bucket_attrs(); + if (opt_bucket_info && opt_attrs) { + source_bucket_info.emplace(); + source_bucket_info->bucket_info = *opt_bucket_info; + source_bucket_info->attrs = *opt_attrs; + } + } if (!target_bucket) { get_hint_targets_action = make_shared(sync_env, *source_bucket); @@ -4267,8 +4490,11 @@ int RGWGetBucketPeersCR::operate() update_from_source_bucket_policy(); for (siiter = buckets_info.begin(); siiter != buckets_info.end(); ++siiter) { - if (siiter->second.bucket.name.empty()) { - yield call(new RGWSyncGetBucketInfoCR(sync_env, siiter->first, &siiter->second, tn)); + if (siiter->second.bucket_info.bucket.name.empty()) { + yield call(new RGWSyncGetBucketInfoCR(sync_env, siiter->first, + &siiter->second.bucket_info, + &siiter->second.attrs, + tn)); } } @@ -4326,7 +4552,8 @@ int RGWRunBucketSyncCoroutine::operate() tn->log(20, SSTR("sync status for source bucket: " << sync_status.state)); - yield call(new RGWSyncGetBucketInfoCR(sync_env, sync_pair.source_bs.bucket, &sync_pipe.source_bucket_info, tn)); + yield call(new RGWSyncGetBucketInfoCR(sync_env, sync_pair.source_bs.bucket, &sync_pipe.source_bucket_info, + &sync_pipe.source_bucket_attrs, tn)); if (retcode < 0) { tn->log(0, SSTR("ERROR: failed to retrieve bucket info for bucket=" << bucket_str{sync_pair.source_bs.bucket})); lease_cr->go_down(); @@ -4334,7 +4561,8 @@ int RGWRunBucketSyncCoroutine::operate() return set_cr_error(retcode); } - yield call(new RGWSyncGetBucketInfoCR(sync_env, sync_pair.dest_bs.bucket, &sync_pipe.dest_bucket_info, tn)); + yield call(new RGWSyncGetBucketInfoCR(sync_env, sync_pair.dest_bs.bucket, &sync_pipe.dest_bucket_info, + &sync_pipe.dest_bucket_attrs, tn)); if (retcode < 0) { tn->log(0, SSTR("ERROR: failed to retrieve bucket info for bucket=" << bucket_str{sync_pair.source_bs.bucket})); lease_cr->go_down(); diff --git a/src/rgw/rgw_data_sync.h b/src/rgw/rgw_data_sync.h index 6a9c9a4d8af..a8ea0e083d1 100644 --- a/src/rgw/rgw_data_sync.h +++ b/src/rgw/rgw_data_sync.h @@ -43,7 +43,9 @@ inline ostream& operator<<(ostream& out, const rgw_bucket_sync_pair_info& p) { struct rgw_bucket_sync_pipe { rgw_bucket_sync_pair_info info; RGWBucketInfo source_bucket_info; + map source_bucket_attrs; RGWBucketInfo dest_bucket_info; + map dest_bucket_attrs; RGWBucketSyncFlowManager::pipe_rules_ref& get_rules() { return info.handler.rules; diff --git a/src/rgw/rgw_trim_bilog.cc b/src/rgw/rgw_trim_bilog.cc index aa075949ffe..ac1ca25df5d 100644 --- a/src/rgw/rgw_trim_bilog.cc +++ b/src/rgw/rgw_trim_bilog.cc @@ -468,7 +468,7 @@ int BucketTrimInstanceCR::operate() } // in parallel, read the local bucket instance info spawn(new RGWGetBucketInstanceInfoCR(store->svc()->rados->get_async_processor(), store, - bucket, &bucket_info), + bucket, &bucket_info, nullptr), false); } // wait for a response from each peer. all must respond to attempt trim diff --git a/src/rgw/services/svc_bucket_sync_sobj.cc b/src/rgw/services/svc_bucket_sync_sobj.cc index da3c9874f24..005f09170a2 100644 --- a/src/rgw/services/svc_bucket_sync_sobj.cc +++ b/src/rgw/services/svc_bucket_sync_sobj.cc @@ -180,12 +180,13 @@ int RGWSI_Bucket_Sync_SObj::do_get_policy_handler(RGWSI_Bucket_X_Ctx& ctx, rgw_cache_entry_info cache_info; RGWBucketInfo bucket_info; + map attrs; int r = svc.bucket_sobj->read_bucket_instance_info(ctx.bi, bucket_key, &bucket_info, nullptr, - nullptr, + &attrs, y, &cache_info); if (r < 0) { @@ -201,7 +202,7 @@ int RGWSI_Bucket_Sync_SObj::do_get_policy_handler(RGWSI_Bucket_X_Ctx& ctx, return -ENOENT; } - e.handler.reset(zone_policy_handler->alloc_child(bucket_info)); + e.handler.reset(zone_policy_handler->alloc_child(bucket_info, std::move(attrs))); r = e.handler->init(y); if (r < 0) { -- 2.39.5