Skip to content

Commit 926ed16

Browse files
committed
rgw: RGWRadosPutObj evals source bucket perm for backward compatibility
As of a3f40b4 we no longer evaluate perms locally for source bucket, this could cause broken permission evaluation dusring upgrade as one zone is not respecting the perm evaluation based on the `rgwx-perm-check-uid` arg. This can be dropped in T+2 release. Signed-off-by: Seena Fallah <[email protected]>
1 parent b0200c6 commit 926ed16

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

src/rgw/driver/rados/rgw_rados.cc

Lines changed: 63 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3509,7 +3509,6 @@ class RGWRadosPutObj : public RGWHTTPStreamRWRequest::ReceiveCB
35093509
{
35103510
const DoutPrefixProvider *dpp;
35113511
CephContext* cct;
3512-
rgw_obj obj;
35133512
rgw::sal::DataProcessor *filter;
35143513
boost::optional<RGWPutObj_Compress>& compressor;
35153514
bool try_etag_verify;
@@ -3528,6 +3527,18 @@ class RGWRadosPutObj : public RGWHTTPStreamRWRequest::ReceiveCB
35283527
uint64_t ofs{0};
35293528
uint64_t lofs{0}; /* logical ofs */
35303529
std::function<int(map<string, bufferlist>&)> attrs_handler;
3530+
/*
3531+
src_bucket_perms, if provided, serves as a fallback mechanism to validate the
3532+
source bucket's ACL before initiating the fetch operation. It ensures
3533+
backward compatibility with legacy implementations where the `rgwx-perm-check-uid`
3534+
arg might not be honored, and the destination zone does not return the
3535+
`x-rgw-perm-checked` header, which confirms that the source object's
3536+
permissions were validated against the specified `rgwx-perm-check-uid`.
3537+
3538+
@todo drop src_bucket_perms and src_obj in T+2 release.
3539+
*/
3540+
const rgw_obj& src_obj;
3541+
const std::optional<RGWUserPermHandler::Bucket>& src_bucket_perms;
35313542

35323543
public:
35333544
RGWRadosPutObj(const DoutPrefixProvider *dpp,
@@ -3537,7 +3548,9 @@ class RGWRadosPutObj : public RGWHTTPStreamRWRequest::ReceiveCB
35373548
rgw::sal::ObjectProcessor *p,
35383549
void (*_progress_cb)(off_t, void *),
35393550
void *_progress_data,
3540-
std::function<int(map<string, bufferlist>&)> _attrs_handler) :
3551+
std::function<int(map<string, bufferlist>&)> _attrs_handler,
3552+
const rgw_obj& src_obj,
3553+
const std::optional<RGWUserPermHandler::Bucket>& _src_bucket_perms = std::nullopt) :
35413554
dpp(dpp),
35423555
cct(cct),
35433556
filter(p),
@@ -3547,7 +3560,9 @@ class RGWRadosPutObj : public RGWHTTPStreamRWRequest::ReceiveCB
35473560
processor(p),
35483561
progress_cb(_progress_cb),
35493562
progress_data(_progress_data),
3550-
attrs_handler(_attrs_handler) {}
3563+
attrs_handler(_attrs_handler),
3564+
src_obj(src_obj),
3565+
src_bucket_perms(_src_bucket_perms) {}
35513566

35523567

35533568
int process_attrs(void) {
@@ -3730,6 +3745,23 @@ class RGWRadosPutObj : public RGWHTTPStreamRWRequest::ReceiveCB
37303745
return "";
37313746
}
37323747
}
3748+
3749+
int handle_headers(const map<string, string>& headers, int http_status) override {
3750+
if (src_bucket_perms && http_status != 403 && http_status != 401) {
3751+
auto iter = headers.find("RGWX_PERM_CHECKED");
3752+
// if the header is not present, we need to check the ACL
3753+
// of the source bucket against the fallback UID
3754+
if (iter == headers.end()) {
3755+
// old ACL should still win s3:ReplicateObject
3756+
if (!src_bucket_perms->verify_bucket_permission(src_obj.key, rgw::IAM::s3ReplicateObject)) {
3757+
ldpp_dout(dpp, 4) << "ERROR: " << __func__ << "(): fallback permission check denied" << dendl;
3758+
return -EACCES;
3759+
}
3760+
}
3761+
}
3762+
3763+
return 0;
3764+
}
37333765
};
37343766

37353767
/*
@@ -4381,6 +4413,32 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& dest_obj_ctx,
43814413

43824414
std::optional<rgw_user> override_owner;
43834415

4416+
// load src bucket perm handler for backward compatibility
4417+
// @todo drop me in t+2 release.
4418+
std::optional<RGWUserPermHandler::Bucket> src_bucket_perms;
4419+
if (perm_check_uid) {
4420+
std::unique_ptr<rgw::sal::Bucket> src_bucket;
4421+
ret = driver->load_bucket(rctx.dpp, src_obj.bucket, &src_bucket, rctx.y);
4422+
if (ret < 0) {
4423+
ldpp_dout(rctx.dpp, 0) << "ERROR: failed to load src bucket=" << src_obj << " ret=" << ret << dendl;
4424+
return ret;
4425+
}
4426+
4427+
RGWUserPermHandler user_perms(rctx.dpp, driver, cct, *perm_check_uid);
4428+
ret = user_perms.init();
4429+
if (ret < 0) {
4430+
ldpp_dout(rctx.dpp, 0) << "ERROR: failed to init user perms for: " << src_obj << " ret=" << ret << dendl;
4431+
return ret;
4432+
}
4433+
4434+
src_bucket_perms.emplace();
4435+
ret = user_perms.init_bucket(src_bucket->get_info(), src_bucket->get_attrs(), &*src_bucket_perms);
4436+
if (ret < 0) {
4437+
ldpp_dout(rctx.dpp, 0) << "ERROR: failed to init bucket perms for: " << src_obj << " ret=" << ret << dendl;
4438+
return ret;
4439+
}
4440+
}
4441+
43844442
RGWRadosPutObj cb(rctx.dpp, cct, plugin, compressor, &processor, progress_cb, progress_data,
43854443
[&](map<string, bufferlist>& obj_attrs) {
43864444
const rgw_placement_rule *ptail_rule;
@@ -4414,7 +4472,7 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& dest_obj_ctx,
44144472
return ret;
44154473
}
44164474
return 0;
4417-
});
4475+
}, src_obj, src_bucket_perms);
44184476

44194477
string etag;
44204478
real_time set_mtime;
@@ -5349,7 +5407,7 @@ int RGWRados::restore_obj_from_cloud(RGWLCCloudTierCtx& tier_ctx,
53495407
}
53505408
cb_processed = true;
53515409
return 0;
5352-
});
5410+
}, dest_obj);
53535411

53545412
// fetch mtime of the object and other attrs of the object
53555413
// to check for restore_status

src/test/rgw/rgw_multi/tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4247,7 +4247,7 @@ def test_bucket_replication_reject_versioning_identical():
42474247
assert e.response['ResponseMetadata']['HTTPStatusCode'] == 400
42484248

42494249
@allow_bucket_replication
4250-
def test_bucket_replicaion_reject_objectlock_identical():
4250+
def test_bucket_replication_reject_objectlock_identical():
42514251
zonegroup = realm.master_zonegroup()
42524252
zonegroup_conns = ZonegroupConns(zonegroup)
42534253

0 commit comments

Comments
 (0)