]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw/sts: maintain backward compatibility with
authorPritha Srivastava <prsrivas@redhat.com>
Mon, 3 Nov 2025 09:20:28 +0000 (14:50 +0530)
committerPritha Srivastava <prsrivas@redhat.com>
Fri, 21 Nov 2025 08:14:12 +0000 (13:44 +0530)
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 <prsrivas@redhat.com>
src/common/options/rgw.yaml.in
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_op.cc
src/rgw/rgw_rest_bucket_logging.cc

index 6d686036593dff41290ad91d395668bfa2749707..213dec952fb8dc8773f862a9062bc7c7948d6b1f 100644 (file)
@@ -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
index fa46beea26e920c7e2c8002fd7099ed61fe9dcfe..54674dde453d873be2b8dbfdf019241d2293ac66 100644 (file)
@@ -1363,7 +1363,9 @@ bool verify_bucket_permission(const DoutPrefixProvider* dpp,
                              const boost::optional<Policy>& bucket_policy,
                               const vector<Policy>& identity_policies,
                               const vector<Policy>& 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<Policy>& bucket_policy,
                               const vector<Policy>& user_policies,
                               const vector<Policy>& 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);
index 3367a5739c1280443dde7a5ab8e069f834978600..738293c4fe30523d55a420c1743547a99188b4ff 100644 (file)
@@ -1825,11 +1825,12 @@ bool verify_bucket_permission(
   const boost::optional<rgw::IAM::Policy>& bucket_policy,
   const std::vector<rgw::IAM::Policy>& identity_policies,
   const std::vector<rgw::IAM::Policy>& 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,
index ca02b9d86de514fd16184ad7f64a8f727bc963dd..0428889a2635fdc422ab6f3b176dba0e6f781edf 100644 (file)
@@ -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;
   }
 
index 71fe28b80626377167d5a2eb58ce0d0585d417e3..8c41106d8ba6d0a8a84cb5be2bf618faee625ce3 100644 (file)
@@ -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;
     }