]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw: add /admin/account rest apis
authorCasey Bodley <cbodley@redhat.com>
Wed, 1 Nov 2023 22:27:42 +0000 (18:27 -0400)
committerCasey Bodley <cbodley@redhat.com>
Fri, 12 Apr 2024 19:34:26 +0000 (15:34 -0400)
Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit cce372dc2ebd2b0d7bdb06b930fcc35ad27147d1)

src/rgw/CMakeLists.txt
src/rgw/rgw_appmain.cc
src/rgw/rgw_common.cc
src/rgw/rgw_common.h
src/rgw/rgw_rest_account.cc [new file with mode: 0644]
src/rgw/rgw_rest_account.h [new file with mode: 0644]

index 3de10300444cfdec8c5d08216c77ecd78353e0fa..64b56492bfaf6e6829893a2578a360650e8ed3f3 100644 (file)
@@ -104,6 +104,7 @@ set(librgw_common_srcs
   rgw_quota.cc
   rgw_resolve.cc
   rgw_rest.cc
+  rgw_rest_account.cc
   rgw_rest_client.cc
   rgw_rest_config.cc
   rgw_rest_conn.cc
index b4aa1019a73983924072f2b18baa9e2366853d20..b3e1765afc0a3e5b78c9e9039bd49c6822a829c4 100644 (file)
@@ -37,6 +37,7 @@
 #include "rgw_rest_admin.h"
 #include "rgw_rest_info.h"
 #include "rgw_rest_usage.h"
+#include "rgw_rest_account.h"
 #include "rgw_rest_bucket.h"
 #include "rgw_rest_metadata.h"
 #include "rgw_rest_log.h"
@@ -360,6 +361,7 @@ void rgw::AppMain::cond_init_apis()
       RGWRESTMgr_Admin *admin_resource = new RGWRESTMgr_Admin;
       admin_resource->register_resource("info", new RGWRESTMgr_Info);
       admin_resource->register_resource("usage", new RGWRESTMgr_Usage);
+      admin_resource->register_resource("account", new RGWRESTMgr_Account);
       /* Register driver-specific admin APIs */
       env.driver->register_admin_apis(admin_resource);
       rest.register_resource(g_conf()->rgw_admin_entry, admin_resource);
index e93efa12f8964562cbce638a69a9d22429f43498..afd2f6dd352cd7166af57846135bd4dc0760cb75 100644 (file)
@@ -133,6 +133,7 @@ rgw_http_errors rgw_http_s3_errors({
     { ERR_NO_SUCH_TAG_SET, {404, "NoSuchTagSet"}},
     { ERR_NO_SUCH_BUCKET_ENCRYPTION_CONFIGURATION, {404, "ServerSideEncryptionConfigurationNotFoundError"}},
     { ERR_NO_SUCH_PUBLIC_ACCESS_BLOCK_CONFIGURATION, {404, "NoSuchPublicAccessBlockConfiguration"}},
+    { ERR_ACCOUNT_EXISTS, {409, "AccountAlreadyExists"}},
 });
 
 rgw_http_errors rgw_http_swift_errors({
index 8f023d1225e67d2c9641059edcc62287723e57d8..61b1d19a9b26e5f4b6b361cbcfc382717f164963 100644 (file)
@@ -322,6 +322,7 @@ static inline const char* to_mime_type(const RGWFormat f)
 #define ERR_INVALID_IDENTITY_TOKEN  2401
 
 #define ERR_NO_SUCH_TAG_SET 2402
+#define ERR_ACCOUNT_EXISTS 2403
 
 #ifndef UINT32_MAX
 #define UINT32_MAX (0xffffffffu)
diff --git a/src/rgw/rgw_rest_account.cc b/src/rgw/rgw_rest_account.cc
new file mode 100644 (file)
index 0000000..1e1d367
--- /dev/null
@@ -0,0 +1,241 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2020 SUSE LLC
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#include "rgw_rest_account.h"
+#include "rgw_account.h"
+#include "rgw_process_env.h"
+
+class RGWOp_Account_Create : public RGWRESTOp {
+public:
+  int check_caps(const RGWUserCaps& caps) override {
+    return caps.check_cap("accounts", RGW_CAP_WRITE);
+  }
+
+  void execute(optional_yield y) override;
+
+  const char* name() const override { return "create_account"; }
+};
+
+void RGWOp_Account_Create::execute(optional_yield y)
+{
+  rgw::account::AdminOpState op_state;
+  RESTArgs::get_string(s, "id", "", &op_state.account_id);
+  RESTArgs::get_string(s, "tenant", "", &op_state.tenant);
+  RESTArgs::get_string(s, "name", "", &op_state.account_name);
+  RESTArgs::get_string(s, "email", "", &op_state.email);
+
+  uint32_t max_users = 0;
+  bool has_max_users = false;
+  RESTArgs::get_uint32(s, "max-users", 0, &max_users, &has_max_users);
+  if (has_max_users) {
+    op_state.max_users = max_users;
+  }
+
+  uint32_t max_roles = 0;
+  bool has_max_roles = false;
+  RESTArgs::get_uint32(s, "max-roles", 0, &max_roles, &has_max_roles);
+  if (has_max_roles) {
+    op_state.max_roles = max_roles;
+  }
+
+  uint32_t max_groups = 0;
+  bool has_max_groups = false;
+  RESTArgs::get_uint32(s, "max-groups", 0, &max_groups, &has_max_groups);
+  if (has_max_groups) {
+    op_state.max_groups = max_groups;
+  }
+
+  uint32_t max_access_keys = 0;
+  bool has_max_access_keys = false;
+  RESTArgs::get_uint32(s, "max-access-keys", 0, &max_access_keys, &has_max_access_keys);
+  if (has_max_access_keys) {
+    op_state.max_access_keys = max_access_keys;
+  }
+
+  uint32_t max_buckets = 0;
+  bool has_max_buckets = false;
+  RESTArgs::get_uint32(s, "max-buckets", 0, &max_buckets, &has_max_buckets);
+  if (has_max_buckets) {
+    op_state.max_buckets = max_buckets;
+  }
+
+  if (!driver->is_meta_master()) {
+    bufferlist data;
+    JSONParser parser;
+    op_ret = rgw_forward_request_to_master(this, *s->penv.site, s->user->get_id(),
+                                           &data, &parser, s->info, y);
+    if (op_ret < 0) {
+      ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
+      return;
+    }
+
+    // the master zone may have generated its own account id, use the same
+    std::string meta_master_id;
+    JSONDecoder::decode_json("id", meta_master_id, &parser);
+    if (meta_master_id.empty()) {
+      ldpp_dout(this, 4) << "forward_request_to_master returned empty account id" << dendl;
+      op_ret = -EINVAL;
+      return;
+    }
+    op_state.account_id = meta_master_id;
+  }
+
+  op_ret = rgw::account::create(this, driver, op_state,
+                                s->err.message, flusher, y);
+  if (op_ret < 0) {
+    if (op_ret == -EEXIST) {
+      op_ret = -ERR_ACCOUNT_EXISTS;
+    }
+  }
+}
+
+class RGWOp_Account_Modify : public RGWRESTOp {
+public:
+  int check_caps(const RGWUserCaps& caps) override {
+    return caps.check_cap("accounts", RGW_CAP_WRITE);
+  }
+
+  void execute(optional_yield y) override;
+
+  const char* name() const override { return "modify_account"; }
+};
+
+void RGWOp_Account_Modify::execute(optional_yield y)
+{
+  bufferlist data;
+  op_ret = rgw_forward_request_to_master(this, *s->penv.site, s->user->get_id(),
+                                         &data, nullptr, s->info, y);
+  if (op_ret < 0) {
+    ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
+    return;
+  }
+
+  rgw::account::AdminOpState op_state;
+  RESTArgs::get_string(s, "id", "", &op_state.account_id);
+  RESTArgs::get_string(s, "tenant", "", &op_state.tenant);
+  RESTArgs::get_string(s, "name", "", &op_state.account_name);
+  RESTArgs::get_string(s, "email", "", &op_state.email);
+
+  uint32_t max_users = 0;
+  bool has_max_users = false;
+  RESTArgs::get_uint32(s, "max-users", 0, &max_users, &has_max_users);
+  if (has_max_users) {
+    op_state.max_users = max_users;
+  }
+
+  uint32_t max_roles = 0;
+  bool has_max_roles = false;
+  RESTArgs::get_uint32(s, "max-roles", 0, &max_roles, &has_max_roles);
+  if (has_max_roles) {
+    op_state.max_roles = max_roles;
+  }
+
+  uint32_t max_groups = 0;
+  bool has_max_groups = false;
+  RESTArgs::get_uint32(s, "max-groups", 0, &max_groups, &has_max_groups);
+  if (has_max_groups) {
+    op_state.max_groups = max_groups;
+  }
+
+  uint32_t max_access_keys = 0;
+  bool has_max_access_keys = false;
+  RESTArgs::get_uint32(s, "max-access-keys", 0, &max_access_keys, &has_max_access_keys);
+  if (has_max_access_keys) {
+    op_state.max_access_keys = max_access_keys;
+  }
+
+  uint32_t max_buckets = 0;
+  bool has_max_buckets = false;
+  RESTArgs::get_uint32(s, "max-buckets", 0, &max_buckets, &has_max_buckets);
+  if (has_max_buckets) {
+    op_state.max_buckets = max_buckets;
+  }
+
+  op_ret = rgw::account::modify(this, driver, op_state,
+                                s->err.message, flusher, y);
+}
+
+
+class RGWOp_Account_Get : public RGWRESTOp {
+public:
+  int check_caps(const RGWUserCaps& caps) override {
+    return caps.check_cap("account", RGW_CAP_READ);
+  }
+
+  void execute(optional_yield y) override;
+
+  const char* name() const override { return "get_account"; }
+};
+
+void RGWOp_Account_Get::execute(optional_yield y)
+{
+  rgw::account::AdminOpState op_state;
+  RESTArgs::get_string(s, "id", "", &op_state.account_id);
+  RESTArgs::get_string(s, "tenant", "", &op_state.tenant);
+  RESTArgs::get_string(s, "name", "", &op_state.account_name);
+
+  op_ret = rgw::account::info(this, driver, op_state,
+                              s->err.message, flusher, y);
+}
+
+class RGWOp_Account_Delete : public RGWRESTOp {
+public:
+  int check_caps(const RGWUserCaps& caps) override {
+    return caps.check_cap("account", RGW_CAP_WRITE);
+  }
+
+  void execute(optional_yield y) override;
+
+  const char* name() const override { return "delete_account"; }
+};
+
+void RGWOp_Account_Delete::execute(optional_yield y)
+{
+  bufferlist data;
+  op_ret = rgw_forward_request_to_master(this, *s->penv.site, s->user->get_id(),
+                                         &data, nullptr, s->info, y);
+  if (op_ret < 0) {
+    ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
+    return;
+  }
+
+  rgw::account::AdminOpState op_state;
+  RESTArgs::get_string(s, "id", "", &op_state.account_id);
+  RESTArgs::get_string(s, "tenant", "", &op_state.tenant);
+  RESTArgs::get_string(s, "name", "", &op_state.account_name);
+
+  op_ret = rgw::account::remove(this, driver, op_state,
+                                s->err.message, flusher, y);
+}
+
+RGWOp* RGWHandler_Account::op_post()
+{
+  return new RGWOp_Account_Create;
+}
+
+RGWOp* RGWHandler_Account::op_put()
+{
+  return new RGWOp_Account_Modify;
+}
+
+RGWOp* RGWHandler_Account::op_get()
+{
+  return new RGWOp_Account_Get;
+}
+
+RGWOp* RGWHandler_Account::op_delete()
+{
+  return new RGWOp_Account_Delete;
+}
diff --git a/src/rgw/rgw_rest_account.h b/src/rgw/rgw_rest_account.h
new file mode 100644 (file)
index 0000000..2df07a0
--- /dev/null
@@ -0,0 +1,46 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab ft=cpp
+
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2020 SUSE LLC
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#pragma once
+
+#include "rgw_rest.h"
+#include "rgw_rest_s3.h"
+
+class RGWHandler_Account : public RGWHandler_Auth_S3 {
+ protected:
+  RGWOp *op_get() override;
+  RGWOp *op_put() override;
+  RGWOp *op_post() override;
+  RGWOp *op_delete() override;
+ public:
+  using RGWHandler_Auth_S3::RGWHandler_Auth_S3;
+  ~RGWHandler_Account() override = default;
+
+  int read_permissions(RGWOp*, optional_yield y) override {
+    return 0;
+  }
+};
+
+class RGWRESTMgr_Account : public RGWRESTMgr {
+ public:
+  RGWRESTMgr_Account() = default;
+  ~RGWRESTMgr_Account() override = default;
+
+  RGWHandler_REST *get_handler(rgw::sal::Driver* driver, struct req_state*,
+                               const rgw::auth::StrategyRegistry& auth_registry,
+                               const std::string&) override {
+    return new RGWHandler_Account(auth_registry);
+  }
+};