return 0;
}
- RGWAccessControlPolicy policy;
+ RGWObjTags obj_tags;
+ bufferlist bl_tag;
+ if (obj->get_attr(RGW_ATTR_TAGS, bl_tag)) {
+ auto bliter = bl_tag.cbegin();
+ try {
+ obj_tags.decode(bliter);
+ } catch (buffer::error &err) {
+ ldpp_dout(dpp, 0) << "ERROR: " << __func__ << ": caught buffer::error couldn't decode TagSet " << dendl;
+ return -EIO;
+ }
+ }
+
+ rgw_sync_pipe_params params;
+ if (!sync_pipe.info.handler.find_obj_params(obj->get_key(),
+ obj_tags.get_tags(),
+ ¶ms)) {
+ return -ERR_PRECONDITION_FAILED;
+ }
+
+ if (params.mode == rgw_sync_pipe_params::MODE_USER) {
+ std::optional<RGWUserPermHandler> user_perms;
+ RGWUserPermHandler::Bucket dest_bucket_perms;
+
+ if (params.user.empty()) {
+ ldpp_dout(dpp, 20) << "ERROR: " << __func__ << ": user level sync but user param not set" << dendl;
+ return -EPERM;
+ }
+ user_perms.emplace(dpp, store, dpp->get_cct(), params.user);
+
+ ret = user_perms->init();
+ if (ret < 0) {
+ ldpp_dout(dpp, 0) << "ERROR: " << __func__ << ": failed to init user perms for uid=" << params.user << " ret=" << ret << dendl;
+ return ret;
+ }
+
+ ret = user_perms->init_bucket(sync_pipe.dest_bucket_info, sync_pipe.dest_bucket_attrs, &dest_bucket_perms);
+ if (ret < 0) {
+ ldpp_dout(dpp, 0) << "ERROR: " << __func__ << ": failed to init bucket perms for uid=" << params.user << " bucket=" << bucket->get_key() << " ret=" << ret << dendl;
+ return ret;
+ }
+
+ if (!dest_bucket_perms.verify_bucket_permission(obj->get_key(), rgw::IAM::s3ReplicateDelete)) {
+ ldpp_dout(dpp, 20) << "ERROR: " << __func__ << ": user does not have permission to delete object" << dendl;
+ return -EPERM;
+ }
+ }
/* decode policy */
+ RGWAccessControlPolicy policy;
bufferlist bl;
if (obj->get_attr(RGW_ATTR_ACL, bl)) {
auto bliter = bl.cbegin();
class RGWAsyncRemoveObj : public RGWAsyncRadosRequest {
const DoutPrefixProvider *dpp;
rgw::sal::RadosStore* store;
+ CephContext *cct;
rgw_zone_id source_zone;
+ rgw_bucket_sync_pipe& sync_pipe;
std::unique_ptr<rgw::sal::Bucket> bucket;
std::unique_ptr<rgw::sal::Object> obj;
int _send_request(const DoutPrefixProvider *dpp) override;
public:
RGWAsyncRemoveObj(const DoutPrefixProvider *_dpp, RGWCoroutine *caller, RGWAioCompletionNotifier *cn,
- rgw::sal::RadosStore* _store,
- const rgw_zone_id& _source_zone,
- RGWBucketInfo& _bucket_info,
- const rgw_obj_key& _key,
- const std::string& _owner,
- const std::string& _owner_display_name,
- bool _versioned,
- uint64_t _versioned_epoch,
- bool _delete_marker,
- bool _if_older,
- real_time& _timestamp,
- rgw_zone_set* _zones_trace) : RGWAsyncRadosRequest(caller, cn), dpp(_dpp), store(_store),
- source_zone(_source_zone),
- owner(_owner),
- owner_display_name(_owner_display_name),
- versioned(_versioned),
- versioned_epoch(_versioned_epoch),
- del_if_older(_if_older),
- timestamp(_timestamp) {
+ rgw::sal::RadosStore* _store,
+ CephContext *_cct,
+ const rgw_zone_id& _source_zone,
+ rgw_bucket_sync_pipe& _sync_pipe,
+ const rgw_obj_key& _key,
+ const std::string& _owner,
+ const std::string& _owner_display_name,
+ bool _versioned,
+ uint64_t _versioned_epoch,
+ bool _delete_marker,
+ bool _if_older,
+ real_time& _timestamp,
+ rgw_zone_set* _zones_trace) : RGWAsyncRadosRequest(caller, cn), dpp(_dpp), store(_store), cct(_cct),
+ source_zone(_source_zone),
+ sync_pipe(_sync_pipe),
+ owner(_owner),
+ owner_display_name(_owner_display_name),
+ versioned(_versioned),
+ versioned_epoch(_versioned_epoch),
+ del_if_older(_if_older),
+ timestamp(_timestamp) {
if (_delete_marker) {
marker_version_id = _key.instance;
}
if (_zones_trace) {
zones_trace = *_zones_trace;
}
- bucket = store->get_bucket(_bucket_info);
+ bucket = store->get_bucket(sync_pipe.dest_bucket_info);
obj = bucket->get_object(_key);
}
};
rgw::sal::RadosStore* store;
rgw_zone_id source_zone;
- RGWBucketInfo bucket_info;
+ rgw_bucket_sync_pipe& sync_pipe;
rgw_obj_key key;
bool versioned;
public:
RGWRemoveObjCR(const DoutPrefixProvider *_dpp, RGWAsyncRadosProcessor *_async_rados, rgw::sal::RadosStore* _store,
const rgw_zone_id& _source_zone,
- RGWBucketInfo& _bucket_info,
+ rgw_bucket_sync_pipe& _sync_pipe,
const rgw_obj_key& _key,
bool _versioned,
uint64_t _versioned_epoch,
rgw_zone_set *_zones_trace) : RGWSimpleCoroutine(_store->ctx()), dpp(_dpp), cct(_store->ctx()),
async_rados(_async_rados), store(_store),
source_zone(_source_zone),
- bucket_info(_bucket_info),
+ sync_pipe(_sync_pipe),
key(_key),
versioned(_versioned),
versioned_epoch(_versioned_epoch),
}
int send_request(const DoutPrefixProvider *dpp) override {
- req = new RGWAsyncRemoveObj(dpp, this, stack->create_completion_notifier(), store, source_zone, bucket_info,
+ req = new RGWAsyncRemoveObj(dpp, this, stack->create_completion_notifier(), store, cct, source_zone, sync_pipe,
key, owner, owner_display_name, versioned, versioned_epoch,
delete_marker, del_if_older, timestamp, zones_trace);
async_rados->queue(req);
{
auto sync_env = sc->env;
return new RGWRemoveObjCR(sync_env->dpp, sync_env->async_rados, sync_env->driver, sc->source_zone,
- sync_pipe.dest_bucket_info, key, versioned, versioned_epoch,
+ sync_pipe, key, versioned, versioned_epoch,
NULL, NULL, false, &mtime, zones_trace);
}
{
auto sync_env = sc->env;
return new RGWRemoveObjCR(sync_env->dpp, sync_env->async_rados, sync_env->driver, sc->source_zone,
- sync_pipe.dest_bucket_info, key, versioned, versioned_epoch,
+ sync_pipe, key, versioned, versioned_epoch,
&owner.id, &owner.display_name, true, &mtime, zones_trace);
}
<< " versioned=" << versioned << " versioned_epoch=" << versioned_epoch << dendl;
auto sync_env = sc->env;
return new RGWRemoveObjCR(sync_env->dpp, sync_env->async_rados, sync_env->driver, sc->source_zone,
- sync_pipe.dest_bucket_info, key, versioned, versioned_epoch,
+ sync_pipe, key, versioned, versioned_epoch,
&owner.id, &owner.display_name, true, &mtime, zones_trace);
}
{ "s3:PutReplicationConfiguration", s3PutReplicationConfiguration },
{ "s3:RestoreObject", s3RestoreObject },
{ "s3:DescribeJob", s3DescribeJob },
+ { "s3:ReplicateDelete", s3ReplicateDelete },
{ "s3-object-lambda:GetObject", s3objectlambdaGetObject },
{ "s3-object-lambda:ListBucket", s3objectlambdaListBucket },
{ "iam:PutUserPolicy", iamPutUserPolicy },
case s3DescribeJob:
return "s3:DescribeJob";
+ case s3ReplicateDelete:
+ return "s3:ReplicateDelete";
+
case s3objectlambdaGetObject:
return "s3-object-lambda:GetObject";