From: Pritha Srivastava Date: Mon, 3 Nov 2025 09:20:28 +0000 (+0530) Subject: rgw/sts: maintain backward compatibility with X-Git-Tag: testing/wip-pdonnell-testing-20260323.122957-tentacle~343 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=10c9032d7c6515b4ed5a2f63f7e3420652b627c0;p=ceph-ci.git rgw/sts: maintain backward compatibility with 7.1 tenant based STS when bucket owner is the same as one assuming the role. resolves: rhbz#2406837 resolves: rhbz#2412223 Signed-off-by: Pritha Srivastava --- diff --git a/src/common/options/rgw.yaml.in b/src/common/options/rgw.yaml.in index 6d686036593..213dec952fb 100644 --- a/src/common/options/rgw.yaml.in +++ b/src/common/options/rgw.yaml.in @@ -4507,4 +4507,14 @@ options: - rgw see_also: - rgw_user_quota_sync_interval +- name: rgw_sts_backward_compatibility_7_1 + type: bool + level: advanced + long_desc: To maintain backward compatibility with 7.1, turn it to true ONLY when + a bucket owner assumes a role, and performs s3 operations, in a tenant based model. + default: false + services: + - rgw + flags: + - startup with_legacy: true diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index fa46beea26e..54674dde453 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -1363,7 +1363,9 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp, const boost::optional& bucket_policy, const vector& identity_policies, const vector& session_policies, - const uint64_t op, bool* granted_by_acl) + const uint64_t op, + bool* granted_by_acl, + bool bucket_owner_comptability) { if (!verify_requester_payer_permission(s)) return false; @@ -1391,6 +1393,31 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp, return true; } + //For backward compatibility with 7.1, return false when + //session policy evaluation returns Effect::Pass and when + //all entities are in a tenant model(user/role/bucket etc) + auto& conf = dpp->get_cct()->_conf; + if (!s->identity->get_account() && + conf->rgw_sts_backward_compatibility_7_1 && + effect == Effect::Pass && + !session_policies.empty()) { + ldpp_dout(dpp, 10) << __func__ << ": explicit deny from session policy for backward compatibility" << dendl; + return false; + } + + //check for bucket ownership in case of a tenant for backward compatibility + if (!s->identity->get_account() && + conf->rgw_sts_backward_compatibility_7_1 && + bucket_owner_comptability) { + if (s->identity->is_owner_of(s->bucket_info.owner)) { + ldpp_dout(dpp, 10) << __func__ << ": backward compatibility check, it is a bucket owner, returning true" << dendl; + return true; + } else { + ldpp_dout(dpp, 10) << __func__ << ": backward compatibility check, it is NOT a bucket owner, returning false" << dendl; + return false; + } + } + const auto perm = op_to_perm(op); return verify_bucket_permission_no_policy(dpp, s, user_acl, bucket_acl, perm, granted_by_acl); } @@ -1403,7 +1430,8 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp, const boost::optional& bucket_policy, const vector& user_policies, const vector& session_policies, - const uint64_t op) + const uint64_t op, + bool bucket_owner_comptability) { perm_state_from_req_state ps(s); auto expected = s->info.env->get("HTTP_X_AMZ_EXPECTED_BUCKET_OWNER"); @@ -1438,7 +1466,7 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp, return verify_bucket_permission(dpp, &ps, arn, account_root, user_acl, bucket_acl, bucket_policy, user_policies, - session_policies, op, &s->granted_by_acl); + session_policies, op, &s->granted_by_acl, bucket_owner_comptability); } bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, @@ -1498,20 +1526,20 @@ bool verify_bucket_permission_no_policy(const DoutPrefixProvider* dpp, req_state } bool verify_bucket_permission(const DoutPrefixProvider* dpp, req_state* s, - const rgw::ARN& arn, uint64_t op) + const rgw::ARN& arn, uint64_t op, bool bucket_owner_comptability) { return verify_bucket_permission(dpp, s, arn, s->user_acl, s->bucket_acl, s->iam_policy, s->iam_identity_policies, - s->session_policies, op); + s->session_policies, op, bucket_owner_comptability); } -bool verify_bucket_permission(const DoutPrefixProvider* dpp, req_state* s, uint64_t op) +bool verify_bucket_permission(const DoutPrefixProvider* dpp, req_state* s, uint64_t op, bool bucket_owner_comptability) { if (rgw::sal::Bucket::empty(s->bucket)) { // request is missing a bucket name return false; } - return verify_bucket_permission(dpp, s, ARN(s->bucket->get_key()), op); + return verify_bucket_permission(dpp, s, ARN(s->bucket->get_key()), op, bucket_owner_comptability); } @@ -1558,6 +1586,18 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct perm_state_b return true; } + //For backward compatibility with 7.1, return false when + //session policy evaluation returns Effect::Pass and when + //all entities are in a tenant model(user/role/bucket etc) + auto& conf = dpp->get_cct()->_conf; + if (!ps->identity->get_account() && + conf->rgw_sts_backward_compatibility_7_1 && + effect == Effect::Pass && + !session_policies.empty()) { + ldpp_dout(dpp, 10) << __func__ << ": explicit deny from session policy for backward compatibility" << dendl; + return false; + } + const auto perm = op_to_perm(op); return verify_object_permission_no_policy(dpp, ps, user_acl, bucket_acl, object_acl, perm, granted_by_acl); diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 3367a5739c1..738293c4fe3 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -1825,11 +1825,12 @@ bool verify_bucket_permission( const boost::optional& bucket_policy, const std::vector& identity_policies, const std::vector& session_policies, - const uint64_t op); + const uint64_t op, + bool bucket_owner_comptability=false); bool verify_bucket_permission(const DoutPrefixProvider* dpp, req_state* s, - const rgw::ARN& arn, uint64_t op); + const rgw::ARN& arn, uint64_t op, bool bucket_owner_comptability=false); bool verify_bucket_permission(const DoutPrefixProvider* dpp, - req_state* s, uint64_t op); + req_state* s, uint64_t op, bool bucket_owner_comptability=false); bool verify_bucket_permission_no_policy( const DoutPrefixProvider* dpp, req_state * const s, diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index ca02b9d86de..0428889a263 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -1414,7 +1414,7 @@ int RGWPutBucketTags::verify_permission(optional_yield y) { if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketTagging)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketTagging, true)) { return -EACCES; } @@ -1454,7 +1454,7 @@ int RGWDeleteBucketTags::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketTagging)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketTagging, true)) { return -EACCES; } @@ -1511,7 +1511,7 @@ int RGWPutBucketReplication::verify_permission(optional_yield y) { if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutReplicationConfiguration)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutReplicationConfiguration, true)) { return -EACCES; } @@ -1561,7 +1561,7 @@ int RGWDeleteBucketReplication::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3DeleteReplicationConfiguration)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3DeleteReplicationConfiguration, true)) { return -EACCES; } @@ -2974,7 +2974,7 @@ int RGWGetBucketVersioning::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketVersioning)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketVersioning, true)) { return -EACCES; } @@ -3004,7 +3004,7 @@ int RGWSetBucketVersioning::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketVersioning)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketVersioning, true)) { return -EACCES; } @@ -3107,7 +3107,7 @@ int RGWGetBucketWebsite::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketWebsite)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketWebsite, true)) { return -EACCES; } @@ -3132,7 +3132,7 @@ int RGWSetBucketWebsite::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketWebsite)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketWebsite, true)) { return -EACCES; } @@ -3183,7 +3183,7 @@ int RGWDeleteBucketWebsite::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3DeleteBucketWebsite)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3DeleteBucketWebsite, true)) { return -EACCES; } @@ -3377,7 +3377,7 @@ int RGWGetBucketLocation::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketLocation)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketLocation, true)) { return -EACCES; } @@ -5636,6 +5636,16 @@ int RGWDeleteObj::verify_permission(optional_yield y) } if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) { + auto& conf = get_cct()->_conf; + if (!s->auth.identity->get_account() && + conf->rgw_sts_backward_compatibility_7_1) { + Effect e = evaluate_iam_policies( + this, s->env, *(s->auth.identity), false, rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key()), + s->iam_policy, s->iam_identity_policies, s->session_policies); + if (e == Effect::Deny) { + bypass_perm = false; + } + } // require s3BypassGovernanceRetention for x-amz-bypass-governance-retention bypass_perm = verify_bucket_permission(this, s, arn, rgw::IAM::s3BypassGovernanceRetention); } @@ -6974,7 +6984,7 @@ int RGWGetCORS::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketCORS)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketCORS, true)) { return -EACCES; } @@ -7000,7 +7010,7 @@ int RGWPutCORS::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketCORS)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketCORS, true)) { return -EACCES; } @@ -7036,7 +7046,7 @@ int RGWDeleteCORS::verify_permission(optional_yield y) rgw_iam_add_buckettags(this, s); // No separate delete permission - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketCORS)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketCORS, true)) { return -EACCES; } @@ -7134,7 +7144,7 @@ int RGWGetRequestPayment::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketRequestPayment)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketRequestPayment, true)) { return -EACCES; } @@ -7157,7 +7167,7 @@ int RGWSetRequestPayment::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketRequestPayment)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketRequestPayment, true)) { return -EACCES; } @@ -7939,8 +7949,19 @@ int RGWDeleteMultiObj::verify_permission(optional_yield y) rgw_iam_add_objtags(this, s, has_s3_existing_tag, has_s3_resource_tag); if (s->bucket->get_info().obj_lock_enabled() && bypass_governance_mode) { - // require s3BypassGovernanceRetention for x-amz-bypass-governance-retention - bypass_perm = verify_bucket_permission(this, s, rgw::IAM::s3BypassGovernanceRetention); + auto& conf = get_cct()->_conf; + if (!s->auth.identity->get_account() && + conf->rgw_sts_backward_compatibility_7_1) { + Effect e = evaluate_iam_policies( + this, s->env, *(s->auth.identity), false, rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket->get_key()), + s->iam_policy, s->iam_identity_policies, s->session_policies); + if (e == Effect::Deny) { + bypass_perm = false; + } + } else { + // require s3BypassGovernanceRetention for x-amz-bypass-governance-retention + bypass_perm = verify_bucket_permission(this, s, rgw::IAM::s3BypassGovernanceRetention); + } } return 0; @@ -9398,7 +9419,7 @@ int RGWPutBucketObjectLock::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketObjectLockConfiguration)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketObjectLockConfiguration, true)) { return -EACCES; } @@ -9481,7 +9502,7 @@ int RGWGetBucketObjectLock::verify_permission(optional_yield y) if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketObjectLockConfiguration)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketObjectLockConfiguration, true)) { return -EACCES; } diff --git a/src/rgw/rgw_rest_bucket_logging.cc b/src/rgw/rgw_rest_bucket_logging.cc index 71fe28b8062..8c41106d8ba 100644 --- a/src/rgw/rgw_rest_bucket_logging.cc +++ b/src/rgw/rgw_rest_bucket_logging.cc @@ -54,7 +54,7 @@ public: if (has_s3_resource_tag) rgw_iam_add_buckettags(this, s); - if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketLogging)) { + if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketLogging, true)) { return -EACCES; }