]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/s3vectors: API should use SigV4 and not SigS3V4
authorYuval Lifshitz <ylifshit@ibm.com>
Tue, 28 Apr 2026 14:26:47 +0000 (14:26 +0000)
committerYuval Lifshitz <ylifshit@ibm.com>
Wed, 1 Jul 2026 15:19:45 +0000 (15:19 +0000)
Signed-off-by: Yuval Lifshitz <ylifshit@ibm.com>
src/rgw/rgw_auth_s3.cc
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3vector.cc
src/rgw/rgw_rest_s3vector.h
src/test/rgw/s3vectors/s3vector_test.py

index 5a68aa63ff2b3412fff11d0894d3e2b1f805100e..3185314f0591e5048796414bbf19c6c8fc6daee2 100644 (file)
@@ -538,6 +538,22 @@ bool is_non_s3_op(RGWOpType op_type)
   case RGW_OP_ATTACH_GROUP_POLICY:
   case RGW_OP_DETACH_GROUP_POLICY:
   case RGW_OP_LIST_ATTACHED_GROUP_POLICIES:
+  case RGW_OP_S3VECTOR_CREATE_INDEX:
+  case RGW_OP_S3VECTOR_CREATE_VECTOR_BUCKET:
+  case RGW_OP_S3VECTOR_DELETE_INDEX:
+  case RGW_OP_S3VECTOR_DELETE_VECTOR_BUCKET:
+  case RGW_OP_S3VECTOR_DELETE_VECTOR_BUCKET_POLICY:
+  case RGW_OP_S3VECTOR_DELETE_VECTORS:
+  case RGW_OP_S3VECTOR_GET_INDEX:
+  case RGW_OP_S3VECTOR_GET_VECTOR_BUCKET:
+  case RGW_OP_S3VECTOR_GET_VECTOR_BUCKET_POLICY:
+  case RGW_OP_S3VECTOR_GET_VECTORS:
+  case RGW_OP_S3VECTOR_LIST_INDEXES:
+  case RGW_OP_S3VECTOR_LIST_VECTOR_BUCKETS:
+  case RGW_OP_S3VECTOR_LIST_VECTORS:
+  case RGW_OP_S3VECTOR_PUT_VECTOR_BUCKET_POLICY:
+  case RGW_OP_S3VECTOR_PUT_VECTORS:
+  case RGW_OP_S3VECTOR_QUERY_VECTORS:
     return true;
   default:
     return false;
index 073032eed97bec99d3466775c784de681b3777eb..6fcaaef6657bcd9de09a23cf229b65794a401c86 100644 (file)
@@ -6170,7 +6170,18 @@ RGWHandler_REST* RGWRESTMgr_S3::get_handler(rgw::sal::Driver* driver,
   // has bucket
   if (enable_s3vector && is_s3vector_op(s)) {
     ldpp_dout(s, 20) << "INFO: s3vector op: " << s->init_state.url_bucket << dendl;
-    return new RGWHandler_REST_s3Vector(auth_registry);
+    const auto max_size = s->cct->_conf->rgw_max_put_param_size;
+    int ret;
+    bufferlist data;
+    std::tie(ret, data) = rgw_rest_read_all_input(s, max_size, false);
+    if (ret < 0) {
+      return nullptr;
+    }
+    if (!s->info.args.exists("PayloadHash")) {
+      const auto payload_hash = rgw::auth::s3::calc_v4_payload_hash(data.to_str());
+      s->info.args.append("PayloadHash", payload_hash);
+    }
+    return new RGWHandler_REST_s3Vector(auth_registry, data);
   }
   return new RGWHandler_REST_Bucket_S3(auth_registry, enable_pubsub);
 }
index 53e1d8e7f299f160c8c9b11aceea2b4dde18d41d..f919b7fe7ef52a2f420c3f855a2997a48ec1c111 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "rgw_op.h"
 #include "rgw_rest_s3vector.h"
+#include "rgw_rest_s3.h"
 #include "rgw_s3vector.h"
 #include "rgw_process_env.h"
 #include "common/async/yield_context.h"
@@ -16,14 +17,11 @@ namespace {
 class RGWS3VectorBase : public RGWDefaultResponseOp {
 protected:
   bufferlist in_data;
+public:
+  explicit RGWS3VectorBase(bufferlist&& data) : in_data(std::move(data)) {}
+protected:
   template<typename T>
   int do_init_processing(T& configuration, optional_yield y) {
-    const auto max_size = s->cct->_conf->rgw_max_put_param_size;
-    int ret = 0;
-    if (std::tie(ret, in_data) = read_all_input(s, max_size, false); ret < 0) {
-      ldpp_dout(this, 1) << "ERROR: failed to read JSON s3vector payload, ret = " << ret << dendl;
-      return ret;
-    }
     if (in_data.length() == 0) {
       ldpp_dout(this, 1) << "ERROR: JSON s3vector payload missing" << dendl;
       return -EINVAL;
@@ -47,7 +45,9 @@ protected:
 
 class RGWS3VectorCreateIndex : public RGWS3VectorBase {
   rgw::s3vector::create_index_t configuration;
-
+public:
+  explicit RGWS3VectorCreateIndex(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector CreateIndex" << dendl;
     // policy TODO: implement permission check
@@ -102,7 +102,9 @@ class RGWS3VectorCreateIndex : public RGWS3VectorBase {
 class RGWS3VectorCreateVectorBucket : public RGWS3VectorBase {
   rgw::s3vector::create_vector_bucket_t configuration;
   std::unique_ptr<rgw::sal::VectorBucket> bucket;
-
+public:
+  explicit RGWS3VectorCreateVectorBucket(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector CreateVectorBucket" << dendl;
     if (s->auth.identity->is_anonymous()) {
@@ -236,7 +238,9 @@ class RGWS3VectorCreateVectorBucket : public RGWS3VectorBase {
 
 class RGWS3VectorDeleteIndex : public RGWS3VectorBase {
   rgw::s3vector::delete_index_t configuration;
-
+public:
+  explicit RGWS3VectorDeleteIndex(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector DeleteIndex" << dendl;
     // policy TODO: implement permission check
@@ -269,7 +273,9 @@ class RGWS3VectorDeleteIndex : public RGWS3VectorBase {
 
 class RGWS3VectorDeleteVectorBucket : public RGWS3VectorBase {
   rgw::s3vector::delete_vector_bucket_t configuration;
-
+public:
+  explicit RGWS3VectorDeleteVectorBucket(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector DeleteVectorBucket" << dendl;
     if (!verify_bucket_permission(this, s, configuration.vector_bucket_arn.get(), rgw::IAM::s3vectorsDeleteVectorBucket)) {
@@ -329,7 +335,9 @@ class RGWS3VectorDeleteVectorBucket : public RGWS3VectorBase {
 
 class RGWS3VectorDeleteVectorBucketPolicy : public RGWS3VectorBase {
   rgw::s3vector::delete_vector_bucket_policy_t configuration;
-
+public:
+  explicit RGWS3VectorDeleteVectorBucketPolicy(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector DeleteVectorBucketPolicy" << dendl;
     // policy TODO: implement permission check
@@ -362,7 +370,9 @@ class RGWS3VectorDeleteVectorBucketPolicy : public RGWS3VectorBase {
 
 class RGWS3VectorPutVectors : public RGWS3VectorBase {
   rgw::s3vector::put_vectors_t configuration;
-
+public:
+  explicit RGWS3VectorPutVectors(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector PutVectors" << dendl;
     // policy TODO: implement permission check
@@ -396,7 +406,9 @@ class RGWS3VectorPutVectors : public RGWS3VectorBase {
 class RGWS3VectorGetVectors : public RGWS3VectorBase {
   rgw::s3vector::get_vectors_t configuration;
   rgw::s3vector::get_vectors_reply_t reply;
-
+public:
+  explicit RGWS3VectorGetVectors(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector GetVectors" << dendl;
     // policy TODO: implement permission check
@@ -448,7 +460,9 @@ class RGWS3VectorGetVectors : public RGWS3VectorBase {
 class RGWS3VectorListVectors : public RGWS3VectorBase {
   rgw::s3vector::list_vectors_t configuration;
   rgw::s3vector::list_vectors_reply_t reply;
-
+public:
+  explicit RGWS3VectorListVectors(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector ListVectors" << dendl;
     // policy TODO: implement permission check
@@ -501,7 +515,9 @@ class RGWS3VectorListVectorBuckets : public RGWS3VectorBase {
   rgw::s3vector::list_vector_buckets_t configuration;
   rgw::sal::BucketList listing;
   std::string zonegroup_name;
-
+public:
+  explicit RGWS3VectorListVectorBuckets(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector ListVectorBuckets" << dendl;
     if (s->auth.identity->is_anonymous()) {
@@ -582,7 +598,9 @@ class RGWS3VectorListVectorBuckets : public RGWS3VectorBase {
 class RGWS3VectorGetVectorBucket : public RGWS3VectorBase {
   rgw::s3vector::get_vector_bucket_t configuration;
   std::unique_ptr<rgw::sal::VectorBucket> bucket;
-
+public:
+  explicit RGWS3VectorGetVectorBucket(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector GetVectorBucket" << dendl;
 
@@ -656,7 +674,9 @@ class RGWS3VectorGetVectorBucket : public RGWS3VectorBase {
 class RGWS3VectorGetIndex : public RGWS3VectorBase {
   rgw::s3vector::get_index_t configuration;
   rgw::s3vector::get_index_reply_t reply;
-
+public:
+  explicit RGWS3VectorGetIndex(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector GetIndex" << dendl;
     // policy TODO: implement permission check
@@ -708,7 +728,9 @@ class RGWS3VectorGetIndex : public RGWS3VectorBase {
 class RGWS3VectorListIndexes : public RGWS3VectorBase {
   rgw::s3vector::list_indexes_t configuration;
   rgw::s3vector::list_indexes_reply_t reply;
-
+public:
+  explicit RGWS3VectorListIndexes(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector ListIndexes" << dendl;
     // policy TODO: implement permission check
@@ -766,7 +788,9 @@ class RGWS3VectorListIndexes : public RGWS3VectorBase {
 
 class RGWS3VectorPutVectorBucketPolicy : public RGWS3VectorBase {
   rgw::s3vector::put_vector_bucket_policy_t configuration;
-
+public:
+  explicit RGWS3VectorPutVectorBucketPolicy(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector PutVectorBucketPolicy" << dendl;
     // policy TODO: implement permission check
@@ -799,7 +823,9 @@ class RGWS3VectorPutVectorBucketPolicy : public RGWS3VectorBase {
 
 class RGWS3VectorGetVectorBucketPolicy : public RGWS3VectorBase {
   rgw::s3vector::get_vector_bucket_policy_t configuration;
-
+public:
+  explicit RGWS3VectorGetVectorBucketPolicy(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector GetVectorBucketPolicy" << dendl;
     // policy TODO: implement permission check
@@ -832,7 +858,9 @@ class RGWS3VectorGetVectorBucketPolicy : public RGWS3VectorBase {
 
 class RGWS3VectorDeleteVectors : public RGWS3VectorBase {
   rgw::s3vector::delete_vectors_t configuration;
-
+public:
+  explicit RGWS3VectorDeleteVectors(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector DeleteVectors" << dendl;
     // policy TODO: implement permission check
@@ -866,7 +894,9 @@ class RGWS3VectorDeleteVectors : public RGWS3VectorBase {
 class RGWS3VectorQueryVectors : public RGWS3VectorBase {
   rgw::s3vector::query_vectors_t configuration;
   rgw::s3vector::query_vectors_reply_t reply;
-
+public:
+  explicit RGWS3VectorQueryVectors(bufferlist&& data) : RGWS3VectorBase(std::move(data)) {}
+private:
   int verify_permission(optional_yield y) override {
     ldpp_dout(this, 10) << "INFO: verifying permission for s3vector QueryVectors" << dendl;
     // policy TODO: implement permission check
@@ -918,47 +948,51 @@ class RGWS3VectorQueryVectors : public RGWS3VectorBase {
 }
 
 int RGWHandler_REST_s3Vector::init(rgw::sal::Driver* driver, req_state *s, rgw::io::BasicClient *cio) {
-  if (int ret = RGWHandler_REST_S3::init(driver, s, cio); ret < 0) {
+  s->dialect = "s3vectors";
+  if (int ret = RGWHandler_REST::init(driver, s, cio); ret < 0) {
     return ret;
   }
-  // s3vectors API uses JSON formatter
   return RGWHandler_REST::allocate_formatter(s, RGWFormat::JSON, false);
 }
 
+int RGWHandler_REST_s3Vector::authorize(const DoutPrefixProvider* dpp, optional_yield y) {
+  return RGW_Auth_S3::authorize(dpp, driver, auth_registry, s, y);
+}
+
 RGWOp* RGWHandler_REST_s3Vector::op_post() {
   const auto& op_name = s->init_state.url_bucket;
   if (op_name == "CreateIndex")
-    return new RGWS3VectorCreateIndex();
+    return new RGWS3VectorCreateIndex(std::move(bl_post_body));
   if (op_name == "CreateVectorBucket")
-    return new RGWS3VectorCreateVectorBucket();
+    return new RGWS3VectorCreateVectorBucket(std::move(bl_post_body));
   if (op_name == "PutVectors")
-    return new RGWS3VectorPutVectors();
+    return new RGWS3VectorPutVectors(std::move(bl_post_body));
   if (op_name == "PutVectorBucketPolicy")
-    return new RGWS3VectorPutVectorBucketPolicy();
+    return new RGWS3VectorPutVectorBucketPolicy(std::move(bl_post_body));
   if (op_name == "DeleteVectors")
-    return new RGWS3VectorDeleteVectors();
+    return new RGWS3VectorDeleteVectors(std::move(bl_post_body));
   if (op_name == "DeleteIndex")
-    return new RGWS3VectorDeleteIndex();
+    return new RGWS3VectorDeleteIndex(std::move(bl_post_body));
   if (op_name == "DeleteVectorBucket")
-    return new RGWS3VectorDeleteVectorBucket();
+    return new RGWS3VectorDeleteVectorBucket(std::move(bl_post_body));
   if (op_name == "DeleteVectorBucketPolicy")
-    return new RGWS3VectorDeleteVectorBucketPolicy();
+    return new RGWS3VectorDeleteVectorBucketPolicy(std::move(bl_post_body));
   if (op_name == "GetIndex")
-    return new RGWS3VectorGetIndex();
+    return new RGWS3VectorGetIndex(std::move(bl_post_body));
   if (op_name == "GetVectors")
-    return new RGWS3VectorGetVectors();
+    return new RGWS3VectorGetVectors(std::move(bl_post_body));
   if (op_name == "GetVectorBucket")
-    return new RGWS3VectorGetVectorBucket();
+    return new RGWS3VectorGetVectorBucket(std::move(bl_post_body));
   if (op_name == "GetVectorBucketPolicy")
-    return new RGWS3VectorGetVectorBucketPolicy();
+    return new RGWS3VectorGetVectorBucketPolicy(std::move(bl_post_body));
   if (op_name == "ListIndexes")
-    return new RGWS3VectorListIndexes();
+    return new RGWS3VectorListIndexes(std::move(bl_post_body));
   if (op_name == "ListVectors")
-    return new RGWS3VectorListVectors();
+    return new RGWS3VectorListVectors(std::move(bl_post_body));
   if (op_name == "ListVectorBuckets")
-    return new RGWS3VectorListVectorBuckets();
+    return new RGWS3VectorListVectorBuckets(std::move(bl_post_body));
   if (op_name == "QueryVectors")
-    return new RGWS3VectorQueryVectors();
+    return new RGWS3VectorQueryVectors(std::move(bl_post_body));
   return nullptr;
 }
 
index 874fde1642ce3b751c7247071a1b0a5fde436810..c8291fd847320e290838a7291dec07e63749402f 100644 (file)
@@ -3,21 +3,21 @@
 
 #pragma once
 
-#include "rgw_rest_s3.h"
+#include "rgw_rest.h"
 
-class RGWHandler_REST_s3Vector : public RGWHandler_REST_S3 {
-protected:
-  int init_permissions(RGWOp* op, optional_yield y) override {return 0;}
-  int read_permissions(RGWOp* op, optional_yield y) override {return 0;}
-  bool supports_quota() override {return false;}
+class RGWHandler_REST_s3Vector : public RGWHandler_REST {
+  const rgw::auth::StrategyRegistry& auth_registry;
+  bufferlist bl_post_body;
+  RGWOp *op_post() override;
 
 public:
-  explicit RGWHandler_REST_s3Vector(const rgw::auth::StrategyRegistry& auth_registry)
-    : RGWHandler_REST_S3(auth_registry) {}
-  virtual ~RGWHandler_REST_s3Vector() = default;
+  RGWHandler_REST_s3Vector(const rgw::auth::StrategyRegistry& auth_registry,
+                           const bufferlist& bl_post_body)
+    : auth_registry(auth_registry), bl_post_body(bl_post_body) {}
+  ~RGWHandler_REST_s3Vector() override = default;
 
   int init(rgw::sal::Driver* driver, req_state *s, rgw::io::BasicClient *cio) override;
-  RGWOp *op_post() override;
-  static RGWOp* create_post_op(const std::string& op_name);
+  int authorize(const DoutPrefixProvider* dpp, optional_yield y) override;
+  int postauth_init(optional_yield y) override { return 0; }
+  int read_permissions(RGWOp* op, optional_yield y) override { return 0; }
 };
-
index cfc508cfe8b4937b7438e194ff59f6a2828d13c7..11ba53bdafae9ffcd58a81441859998ab3229227 100644 (file)
@@ -61,17 +61,11 @@ def connection(service_name='s3vectors'):
     else:
         scheme = 'http://'
 
-    if service_name == 's3vectors':
-        config = Config(signature_version='s3v4')
-    else:
-        config = None
-
     client = boto3.client(service_name,
             endpoint_url=scheme+hostname+':'+str(port_no),
             aws_access_key_id=access_key,
             aws_secret_access_key=secret_key,
-            region_name=get_config_zonegroup(),
-            config=config)
+            region_name=get_config_zonegroup())
 
     return client
 
@@ -91,17 +85,11 @@ def connection2(service_name='s3vectors'):
     else:
         scheme = 'http://'
 
-    if service_name == 's3vectors':
-        config = Config(signature_version='s3v4')
-    else:
-        config = None
-
     client = boto3.client(service_name,
             endpoint_url=scheme+hostname+':'+str(port_no),
             aws_access_key_id=access_key,
             aws_secret_access_key=secret_key,
-            region_name=get_config_zonegroup(),
-            config=config)
+            region_name=get_config_zonegroup())
 
     return client
 
@@ -127,8 +115,7 @@ def another_user(tenant=None):
             endpoint_url=scheme+hostname+':'+str(port_no),
             aws_access_key_id=access_key,
             aws_secret_access_key=secret_key,
-            region_name=get_config_zonegroup(),
-            config=Config(signature_version='s3v4'))
+            region_name=get_config_zonegroup())
 
     return client