]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/iam: refactor OIDC ops
authorCasey Bodley <cbodley@redhat.com>
Mon, 5 Feb 2024 22:49:42 +0000 (17:49 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 12 Apr 2024 19:34:28 +0000 (15:34 -0400)
rearrange the RGWRESTOp subclasses so that the base RGWRestOIDCProvider
can provide a simple verify_permission() that works the same for all
derived ops

Signed-off-by: Casey Bodley <cbodley@redhat.com>
(cherry picked from commit fcbc684e44abc0b336682a8f1d3b2ed072a9a359)

src/rgw/rgw_rest_oidc_provider.cc
src/rgw/rgw_rest_oidc_provider.h

index c50b067d58dba81d4933f3830c4c0493cf41d0a6..e47239a67512e0735c4a4c6263ed00cd4a0ca198 100644 (file)
@@ -24,32 +24,16 @@ using namespace std;
 
 int RGWRestOIDCProvider::verify_permission(optional_yield y)
 {
-  if (s->auth.identity->is_anonymous()) {
-    return -EACCES;
+  if (verify_user_permission(this, s, resource, action)) {
+    return 0;
   }
 
-  provider_arn = s->info.args.get("OpenIDConnectProviderArn");
-  if (provider_arn.empty()) {
-    ldpp_dout(this, 20) << "ERROR: Provider ARN is empty"<< dendl;
-    return -EINVAL;
-  }
-
-  auto ret = check_caps(s->user->get_caps());
-  if (ret == 0) {
-    return ret;
-  }
-
-  uint64_t op = get_op();
-  auto rgw_arn = rgw::ARN::parse(provider_arn, true);
-  if (rgw_arn) {
-    if (!verify_user_permission(this, s, *rgw_arn, op)) {
-      return -EACCES;
-    }
-  } else {
-      return -EACCES;
-  }
+  return RGWRESTOp::verify_permission(y);
+}
 
-  return 0;
+int RGWRestOIDCProvider::check_caps(const RGWUserCaps& caps)
+{
+  return caps.check_cap("roles", perm);
 }
 
 void RGWRestOIDCProvider::send_response()
@@ -61,42 +45,19 @@ void RGWRestOIDCProvider::send_response()
   end_header(s, this);
 }
 
-int RGWRestOIDCProviderRead::check_caps(const RGWUserCaps& caps)
-{
-    return caps.check_cap("oidc-provider", RGW_CAP_READ);
-}
 
-int RGWRestOIDCProviderWrite::check_caps(const RGWUserCaps& caps)
+RGWCreateOIDCProvider::RGWCreateOIDCProvider()
+  : RGWRestOIDCProvider(rgw::IAM::iamCreateOIDCProvider, RGW_CAP_WRITE)
 {
-    return caps.check_cap("oidc-provider", RGW_CAP_WRITE);
 }
 
-int RGWCreateOIDCProvider::verify_permission(optional_yield y)
-{
-  if (s->auth.identity->is_anonymous()) {
-    return -EACCES;
-  }
-
-  auto ret = check_caps(s->user->get_caps());
-  if (ret == 0) {
-    return ret;
-  }
-
-  string idp_url = url_remove_prefix(provider_url);
-  if (!verify_user_permission(this,
-                              s,
-                              rgw::ARN(idp_url,
-                                        "oidc-provider",
-                                         s->user->get_tenant(), true),
-                                         get_op())) {
-    return -EACCES;
-  }
-  return 0;
-}
-
-int RGWCreateOIDCProvider::get_params()
+int RGWCreateOIDCProvider::init_processing(optional_yield y)
 {
   provider_url = s->info.args.get("Url");
+  if (provider_url.empty()) {
+    s->err.message = "Missing required element Url";
+    return -EINVAL;
+  }
 
   auto val_map = s->info.args.get_params();
   for (auto& it : val_map) {
@@ -108,21 +69,18 @@ int RGWCreateOIDCProvider::get_params()
       }
   }
 
-  if (provider_url.empty() || thumbprints.empty()) {
-    ldpp_dout(this, 20) << "ERROR: one of url or thumbprints is empty" << dendl;
+  if (thumbprints.empty()) {
+    s->err.message = "Missing required element ThumbprintList";
     return -EINVAL;
   }
 
+  string idp_url = url_remove_prefix(provider_url);
+  resource = rgw::ARN(idp_url, "oidc-provider/", s->user->get_tenant(), true);
   return 0;
 }
 
 void RGWCreateOIDCProvider::execute(optional_yield y)
 {
-  op_ret = get_params();
-  if (op_ret < 0) {
-    return;
-  }
-
   std::unique_ptr<rgw::sal::RGWOIDCProvider> provider = driver->get_oidc_provider();
   provider->set_url(provider_url);
   provider->set_tenant(s->user->get_tenant());
@@ -140,7 +98,36 @@ void RGWCreateOIDCProvider::execute(optional_yield y)
     s->formatter->close_section();
     s->formatter->close_section();
   }
+}
+
+
+static int validate_provider_arn(const std::string& provider_arn,
+                                 rgw::ARN& resource, std::string& message)
+{
+  if (provider_arn.empty()) {
+    message = "Missing required element OpenIDConnectProviderArn";
+    return -EINVAL;
+  }
+
+  auto arn = rgw::ARN::parse(provider_arn, true);
+  if (!arn) {
+    message = "Invalid value for OpenIDConnectProviderArn";
+    return -EINVAL;
+  }
+  resource = std::move(*arn);
+  return 0;
+}
+
+
+RGWDeleteOIDCProvider::RGWDeleteOIDCProvider()
+  : RGWRestOIDCProvider(rgw::IAM::iamDeleteOIDCProvider, RGW_CAP_WRITE)
+{
+}
 
+int RGWDeleteOIDCProvider::init_processing(optional_yield y)
+{
+  provider_arn = s->info.args.get("OpenIDConnectProviderArn");
+  return validate_provider_arn(provider_arn, resource, s->err.message);
 }
 
 void RGWDeleteOIDCProvider::execute(optional_yield y)
@@ -163,6 +150,17 @@ void RGWDeleteOIDCProvider::execute(optional_yield y)
   }
 }
 
+RGWGetOIDCProvider::RGWGetOIDCProvider()
+  : RGWRestOIDCProvider(rgw::IAM::iamGetOIDCProvider, RGW_CAP_READ)
+{
+}
+
+int RGWGetOIDCProvider::init_processing(optional_yield y)
+{
+  provider_arn = s->info.args.get("OpenIDConnectProviderArn");
+  return validate_provider_arn(provider_arn, resource, s->err.message);
+}
+
 void RGWGetOIDCProvider::execute(optional_yield y)
 {
   std::unique_ptr<rgw::sal::RGWOIDCProvider> provider = driver->get_oidc_provider();
@@ -186,24 +184,10 @@ void RGWGetOIDCProvider::execute(optional_yield y)
   }
 }
 
-int RGWListOIDCProviders::verify_permission(optional_yield y)
-{
-  if (s->auth.identity->is_anonymous()) {
-    return -EACCES;
-  }
-
-  if (int ret = check_caps(s->user->get_caps()); ret == 0) {
-    return ret;
-  }
 
-  if (!verify_user_permission(this, 
-                              s,
-                              rgw::ARN(),
-                              get_op())) {
-    return -EACCES;
-  }
-
-  return 0;
+RGWListOIDCProviders::RGWListOIDCProviders()
+  : RGWRestOIDCProvider(rgw::IAM::iamListOIDCProviders, RGW_CAP_READ)
+{
 }
 
 void RGWListOIDCProviders::execute(optional_yield y)
index 33535c6b5123d4e498633f55d49f117b10ea0efe..14f71af17eb1594ff236b1ed6c6de4c8d49a9000 100644 (file)
@@ -7,65 +7,60 @@
 #include "rgw_oidc_provider.h"
 
 class RGWRestOIDCProvider : public RGWRESTOp {
+  const uint64_t action;
+  const uint32_t perm;
 protected:
-  std::vector<std::string> client_ids;
-  std::vector<std::string> thumbprints;
-  std::string provider_url; //'iss' field in JWT
-  std::string provider_arn;
-public:
-  int verify_permission(optional_yield y) override;
-  void send_response() override;
-  virtual uint64_t get_op() = 0;
-};
+  rgw::ARN resource; // must be initialized before verify_permission()
 
-class RGWRestOIDCProviderRead : public RGWRestOIDCProvider {
-public:
-  RGWRestOIDCProviderRead() = default;
   int check_caps(const RGWUserCaps& caps) override;
-};
 
-class RGWRestOIDCProviderWrite : public RGWRestOIDCProvider {
+  RGWRestOIDCProvider(uint64_t action, uint32_t perm)
+    : action(action), perm(perm) {}
 public:
-  RGWRestOIDCProviderWrite() = default;
-  int check_caps(const RGWUserCaps& caps) override;
+  int verify_permission(optional_yield y) override;
+  void send_response() override;
 };
 
-class RGWCreateOIDCProvider : public RGWRestOIDCProviderWrite {
-public:
-  RGWCreateOIDCProvider() = default;
-  int verify_permission(optional_yield y) override;
+class RGWCreateOIDCProvider : public RGWRestOIDCProvider {
+  std::vector<std::string> client_ids;
+  std::vector<std::string> thumbprints;
+  std::string provider_url; //'iss' field in JWT
+ public:
+  RGWCreateOIDCProvider();
+
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "create_oidc_provider"; }
   RGWOpType get_type() override { return RGW_OP_CREATE_OIDC_PROVIDER; }
-  uint64_t get_op() override { return rgw::IAM::iamCreateOIDCProvider; }
 };
 
-class RGWDeleteOIDCProvider : public RGWRestOIDCProviderWrite {
-public:
-  RGWDeleteOIDCProvider() = default;
+class RGWDeleteOIDCProvider : public RGWRestOIDCProvider {
+  std::string provider_arn;
+ public:
+  RGWDeleteOIDCProvider();
+
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
   const char* name() const override { return "delete_oidc_provider"; }
   RGWOpType get_type() override { return RGW_OP_DELETE_OIDC_PROVIDER; }
-  uint64_t get_op() override { return rgw::IAM::iamDeleteOIDCProvider; }
 };
 
-class RGWGetOIDCProvider : public RGWRestOIDCProviderRead {
-public:
-  RGWGetOIDCProvider() = default;
+class RGWGetOIDCProvider : public RGWRestOIDCProvider {
+  std::string provider_arn;
+ public:
+  RGWGetOIDCProvider();
+
+  int init_processing(optional_yield y) override;
   void execute(optional_yield y) override;
   const char* name() const override { return "get_oidc_provider"; }
   RGWOpType get_type() override { return RGW_OP_GET_OIDC_PROVIDER; }
-  uint64_t get_op() override { return rgw::IAM::iamGetOIDCProvider; }
 };
 
-class RGWListOIDCProviders : public RGWRestOIDCProviderRead {
-public:
-  RGWListOIDCProviders() = default;
-  int verify_permission(optional_yield y) override;
+class RGWListOIDCProviders : public RGWRestOIDCProvider {
+ public:
+  RGWListOIDCProviders();
+
   void execute(optional_yield y) override;
-  int get_params();
   const char* name() const override { return "list_oidc_providers"; }
   RGWOpType get_type() override { return RGW_OP_LIST_OIDC_PROVIDERS; }
-  uint64_t get_op() override { return rgw::IAM::iamListOIDCProviders; }
 };