]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Check S3 object lock date in multi-object delete
authorMark Houghton <mhoughton@microfocus.com>
Thu, 15 Oct 2020 11:13:50 +0000 (12:13 +0100)
committerMatt Benjamin <mbenjamin@redhat.com>
Thu, 6 May 2021 13:48:05 +0000 (09:48 -0400)
Multi-object delete (via the S3 API) will now check each object's retention date in the same way as single object delet does.

Fixes: http://tracker.ceph.com/issues/47586
Signed-off-by: Mark Houghton <mhoughton@microfocus.com>
(cherry picked from commit 1a3f08550813e719b34a8133b83eefa97dd43d3a)
Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
 Conflicts:
src/rgw/rgw_common.h
src/rgw/rgw_common.cc
src/rgw/rgw_op.cc

Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_op.cc

index 567b80ca6c8ec0b09de50e26f4a3ce38b0ea2c2d..0abd7e0c26f96489ee4943090d0624216857ad07 100644 (file)
@@ -1352,6 +1352,39 @@ bool verify_object_permission(const DoutPrefixProvider* dpp, struct req_state *s
                                   op);
 }
 
+int verify_object_lock(const DoutPrefixProvider* dpp, const map<string, buffer::list>& attrs, const bool bypass_perm, const bool bypass_governance_mode) {
+  auto aiter = attrs.find(RGW_ATTR_OBJECT_RETENTION);
+  if (aiter != attrs.end()) {
+    RGWObjectRetention obj_retention;
+    try {
+      decode(obj_retention, aiter->second);
+    } catch (buffer::error& err) {
+      ldpp_dout(dpp, 0) << "ERROR: failed to decode RGWObjectRetention" << dendl;
+      return -EIO;
+    }
+    if (ceph::real_clock::to_time_t(obj_retention.get_retain_until_date()) > ceph_clock_now()) {
+      if (obj_retention.get_mode().compare("GOVERNANCE") != 0 || !bypass_perm || !bypass_governance_mode) {
+        return -EACCES;
+      }
+    }
+  }
+  aiter = attrs.find(RGW_ATTR_OBJECT_LEGAL_HOLD);
+  if (aiter != attrs.end()) {
+    RGWObjectLegalHold obj_legal_hold;
+    try {
+      decode(obj_legal_hold, aiter->second);
+    } catch (buffer::error& err) {
+      ldpp_dout(dpp, 0) << "ERROR: failed to decode RGWObjectLegalHold" << dendl;
+      return -EIO;
+    }
+    if (obj_legal_hold.is_enabled()) {
+      return -EACCES;
+    }
+  }
+  
+  return 0;
+}
+
 class HexTable
 {
   char table[256];
index 3911ab186481aec19a7f98ca32b85b4676f85f7a..18f69e7950dd24804ffc850c7b8b25a77c1d53e3 100644 (file)
@@ -2569,6 +2569,9 @@ extern bool verify_object_permission_no_policy(
   int perm);
 extern bool verify_object_permission_no_policy(const DoutPrefixProvider* dpp, struct req_state *s,
                                               int perm);
+
+int verify_object_lock(const DoutPrefixProvider* dpp, const map<string, buffer::list>& attrs, const bool bypass_perm, const bool bypass_governance_mode);
+
 /** Convert an input URL into a sane object name
  * by converting %-escaped strings into characters, etc*/
 extern void rgw_uri_escape_char(char c, string& dst);
index 80d29ede6edce72ab08229b32c29ce994eb039ca..01e2a7929a1b6645f1af41d6c83a77e1096e2fc8 100644 (file)
@@ -4691,38 +4691,11 @@ void RGWDeleteObj::execute()
     }
 
     if (check_obj_lock) {
-      auto aiter = attrs.find(RGW_ATTR_OBJECT_RETENTION);
-      if (aiter != attrs.end()) {
-        RGWObjectRetention obj_retention;
-        try {
-          decode(obj_retention, aiter->second);
-        } catch (buffer::error& err) {
-          ldpp_dout(this, 0) << "ERROR: failed to decode RGWObjectRetention" << dendl;
-          op_ret = -EIO;
-          return;
-        }
-        if (ceph::real_clock::to_time_t(obj_retention.get_retain_until_date()) > ceph_clock_now()) {
-          if (obj_retention.get_mode().compare("GOVERNANCE") != 0 || !bypass_perm || !bypass_governance_mode) {
-            op_ret = -EACCES;
-            return;
-          }
-        }
-      }
-      aiter = attrs.find(RGW_ATTR_OBJECT_LEGAL_HOLD);
-      if (aiter != attrs.end()) {
-        RGWObjectLegalHold obj_legal_hold;
-        try {
-          decode(obj_legal_hold, aiter->second);
-        } catch (buffer::error& err) {
-          ldpp_dout(this, 0) << "ERROR: failed to decode RGWObjectLegalHold" << dendl;
-          op_ret = -EIO;
-          return;
-        }
-        if (obj_legal_hold.is_enabled()) {
-          op_ret = -EACCES;
-          return;
-        }
-      }
+      int object_lock_response = verify_object_lock(this, attrs, bypass_perm, bypass_governance_mode);
+      if (object_lock_response != 0) {
+        op_ret = object_lock_response;
+        return;
+       }
     }
 
     if (multipart_delete) {
@@ -6419,6 +6392,7 @@ void RGWDeleteMultiObj::execute()
         iter != multi_delete->objects.end();
         ++iter) {
     rgw_obj obj(bucket, *iter);
+    map<string, bufferlist> attrs;
     if (s->iam_policy || ! s->iam_user_policies.empty()) {
       auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
                                               boost::none,
@@ -6447,6 +6421,30 @@ void RGWDeleteMultiObj::execute()
       }
     }
 
+    // verify_object_lock
+    bool check_obj_lock = obj.key.have_instance() && s->bucket_info.obj_lock_enabled();
+    if (check_obj_lock) {
+      int get_attrs_response = get_obj_attrs(store, s, obj, attrs);
+      if (get_attrs_response < 0) {
+        if (get_attrs_response == -ENOENT) {
+          // object maybe delete_marker, skip check_obj_lock
+          check_obj_lock = false;
+        } else {
+          // Something went wrong.
+          send_partial_response(*iter, false, "", get_attrs_response);
+          continue;
+        }
+      }
+    }
+
+    if (check_obj_lock) {
+      int object_lock_response = verify_object_lock(this, attrs, bypass_perm, bypass_governance_mode);
+      if (object_lock_response != 0) {
+        send_partial_response(*iter, false, "", object_lock_response);
+        continue;
+      }
+    }
+
     obj_ctx->set_atomic(obj);
 
     RGWRados::Object del_target(store, s->bucket_info, *obj_ctx, obj);