]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: SysReqApplier overrides is_admin_of based on impersonation
authorSeena Fallah <seenafallah@gmail.com>
Thu, 17 Apr 2025 12:55:00 +0000 (14:55 +0200)
committerSeena Fallah <seenafallah@gmail.com>
Mon, 28 Apr 2025 16:56:06 +0000 (18:56 +0200)
SysReqApplier now returns true for is_admin_of() when the requester
was a system user and was not impersonating any user/role using
rgwx-perm-check-uid or rgwx-perm-check-role.

Signed-off-by: Seena Fallah <seenafallah@gmail.com>
src/rgw/rgw_auth.cc
src/rgw/rgw_auth.h
src/rgw/rgw_auth_filters.h
src/rgw/rgw_auth_s3.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_s3.h
src/rgw/rgw_swift_auth.cc
src/rgw/rgw_swift_auth.h

index 9bb5724e8ccc1809550bd7ded29bf37baf4f81c8..c971b5271a4af8e4084efb4837fe155223247bb1 100644 (file)
@@ -1325,7 +1325,8 @@ rgw::auth::AnonymousEngine::authenticate(const DoutPrefixProvider* dpp, const re
     auto apl = \
       apl_factory->create_apl_local(cct, s, std::move(user), std::nullopt, {},
                                     rgw::auth::LocalApplier::NO_SUBUSER,
-                                    std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
+                                    std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY,
+                                    false /* is_impersonating */);
     return result_t::grant(std::move(apl));
   }
 }
index be1d9eeb41623efacc6cdb51e9a1e3bbf2b5dc76..7b38d198e0139e1d9ae259af50d88e35b15ce603 100644 (file)
@@ -769,7 +769,8 @@ public:
                                       std::vector<IAM::Policy> policies,
                                       const std::string& subuser,
                                       const std::optional<uint32_t>& perm_mask,
-                                      const std::string& access_key_id) const = 0;
+                                      const std::string& access_key_id,
+                                      bool is_impersonating) const = 0;
     };
 };
 
index d15bb54661c5ccc29ddfce7fa4a59fff4271c8c1..dc6e5f7ce8439f4910a61ccc75abc5354ce7c928 100644 (file)
@@ -240,7 +240,8 @@ class SysReqApplier : public DecoratedApplier<T> {
   CephContext* const cct;
   rgw::sal::Driver* driver;
   const RGWHTTPArgs& args;
-  mutable boost::tribool is_system;
+  mutable boost::tribool is_system = boost::logic::indeterminate;
+  mutable bool is_impersonating;
   mutable std::optional<ACLOwner> effective_owner;
   mutable std::optional<std::string> effective_tenant;
 
@@ -249,12 +250,17 @@ public:
   SysReqApplier(CephContext* const cct,
                rgw::sal::Driver* driver,
                 const req_state* const s,
-                U&& decoratee)
+                U&& decoratee,
+                bool is_impersonating = false)
     : DecoratedApplier<T>(std::forward<T>(decoratee)),
       cct(cct),
       driver(driver),
       args(s->info.args),
-      is_system(boost::logic::indeterminate) {
+      is_impersonating(is_impersonating) {
+    if (is_impersonating) {
+      // we only accept impersonated requests from a system user
+      is_system = true;
+    }
   }
 
   void to_str(std::ostream& out) const override;
@@ -275,6 +281,13 @@ public:
     return DecoratedApplier<T>::get_tenant();
   }
 
+  bool is_admin_of(const rgw_owner& o) const override {
+    if (is_system && !is_impersonating) {
+      return true;
+    }
+
+    return DecoratedApplier<T>::is_admin_of(o);
+  }
 };
 
 template <typename T>
@@ -292,8 +305,13 @@ template <typename T>
 auto SysReqApplier<T>::load_acct_info(const DoutPrefixProvider* dpp) const -> std::unique_ptr<rgw::sal::User>
 {
   std::unique_ptr<rgw::sal::User> user = DecoratedApplier<T>::load_acct_info(dpp);
-  is_system = user->get_info().system;
 
+  // skip loading the account info if we already have it through impersonation
+  if (is_impersonating) {
+    return user;
+  }
+
+  is_system = user->get_info().system;
   if (is_system) {
     //ldpp_dout(dpp, 20) << "system request" << dendl;
 
@@ -320,7 +338,7 @@ auto SysReqApplier<T>::load_acct_info(const DoutPrefixProvider* dpp) const -> st
           throw -EACCES;
         }
         effective_tenant = info.tenant;
-     }
+      }
     }
   }
   return user;
@@ -344,8 +362,9 @@ template <typename T> static inline
 SysReqApplier<T> add_sysreq(CephContext* const cct,
                            rgw::sal::Driver* driver,
                             const req_state* const s,
-                            T&& t) {
-  return SysReqApplier<T>(cct, driver, s, std::forward<T>(t));
+                            T&& t,
+                            bool is_impersonating = false) {
+  return SysReqApplier<T>(cct, driver, s, std::forward<T>(t), is_impersonating);
 }
 
 } /* namespace auth */
index b6fc6ef1e083771c911a02e188c267abeb5eed4c..edc208e956740bc72e7e3ba522d70b6fec1ac28f 100644 (file)
@@ -60,10 +60,11 @@ class STSAuthStrategy : public rgw::auth::Strategy,
                             std::vector<IAM::Policy> policies,
                             const std::string& subuser,
                             const std::optional<uint32_t>& perm_mask,
-                            const std::string& access_key_id) const override {
+                            const std::string& access_key_id,
+                            bool is_impersonating) const override {
     auto apl = rgw::auth::add_sysreq(cct, driver, s,
       LocalApplier(cct, std::move(user), std::move(account), std::move(policies),
-                   subuser, perm_mask, access_key_id));
+                   subuser, perm_mask, access_key_id), is_impersonating);
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
 
@@ -182,10 +183,11 @@ class AWSAuthStrategy : public rgw::auth::Strategy,
                             std::vector<IAM::Policy> policies,
                             const std::string& subuser,
                             const std::optional<uint32_t>& perm_mask,
-                            const std::string& access_key_id) const override {
+                            const std::string& access_key_id,
+                            bool is_impersonating) const override {
     auto apl = rgw::auth::add_sysreq(cct, driver, s,
       LocalApplier(cct, std::move(user), std::move(account), std::move(policies),
-                   subuser, perm_mask, access_key_id));
+                   subuser, perm_mask, access_key_id), is_impersonating);
     /* TODO(rzarzynski): replace with static_ptr. */
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
index c591b131b287ad92d381b8f56adcb3d8f0257737..277cb1b79305c33ab0a6b2656081fbcc3484e074 100644 (file)
@@ -6856,7 +6856,7 @@ rgw::auth::s3::LocalEngine::authenticate(
   if (s->op_type == RGW_OP_OPTIONS_CORS) {
     auto apl = apl_factory->create_apl_local(
         cct, s, std::move(user), std::move(account), std::move(policies),
-        k.subuser, std::nullopt, access_key_id);
+        k.subuser, std::nullopt, access_key_id, false /* is_impersonating */);
     return result_t::grant(std::move(apl), completer_factory(k.key));
   }
 
@@ -6875,9 +6875,46 @@ rgw::auth::s3::LocalEngine::authenticate(
     return result_t::deny(-ERR_SIGNATURE_NO_MATCH);
   }
 
-  auto apl = apl_factory->create_apl_local(
-      cct, s, std::move(user), std::move(account), std::move(policies),
-      k.subuser, std::nullopt, access_key_id);
+  aplptr_t apl;
+
+  // if this is a system request and we have rgwx-perm-check-uid passed,
+  // we do impersonation
+  if (user->get_info().system) {
+    const std::string perm_check_uid = s->info.args.get(RGW_SYS_PARAM_PREFIX "perm-check-uid");
+    if (!perm_check_uid.empty()) {
+      auto perm_check_user = driver->get_user(rgw_user(perm_check_uid));
+      if (int r = perm_check_user->load_user(dpp, y); r < 0) {
+        ldpp_dout(dpp, 0) << "ERROR: unable to load user info for "
+                          << perm_check_uid << dendl;
+        return result_t::deny(r);
+      }
+
+      account.reset();
+      policies.clear();
+      // load account and policies for the impersonated user
+      int ret = load_account_and_policies(dpp, y, driver, perm_check_user->get_info(),
+                                          perm_check_user->get_attrs(), account, policies);
+      if (ret < 0) {
+        ldpp_dout(dpp, 0) << "ERROR: unable to load account and policies for "
+                          << perm_check_uid << dendl;
+        return result_t::deny(ret);
+      }
+
+      apl = apl_factory->create_apl_local(
+          cct, s, std::move(perm_check_user), std::move(account), std::move(policies),
+          rgw::auth::LocalApplier::NO_SUBUSER, std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY,
+          true /* is_impersonating */);
+    }
+  }
+
+  if (!apl) {
+    // if we don't have impersonation, use the original user
+    // and the original access key id for logging
+    apl = apl_factory->create_apl_local(
+        cct, s, std::move(user), std::move(account), std::move(policies),
+        k.subuser, std::nullopt, access_key_id, false /* is_impersonating */);
+  }
+
   return result_t::grant(std::move(apl), completer_factory(k.key));
 }
 
@@ -7114,7 +7151,7 @@ rgw::auth::s3::STSEngine::authenticate(
     string subuser;
     auto apl = local_apl_factory->create_apl_local(
         cct, s, std::move(user), std::move(account), std::move(policies),
-        subuser, token.perm_mask, std::string(_access_key_id));
+        subuser, token.perm_mask, std::string(_access_key_id), false /* is_impersonating */);
     return result_t::grant(std::move(apl), completer_factory(token.secret_access_key));
   }
 }
index e8fdc69751c41a9570c3a081f0c8e51bbfeb145b..62445b032707fb207244a1efc4406b3c1e995615 100644 (file)
@@ -1159,6 +1159,7 @@ public:
 };
 
 class LocalEngine : public AWSEngine {
+  typedef rgw::auth::IdentityApplier::aplptr_t aplptr_t;
   rgw::sal::Driver* driver;
   const rgw::auth::LocalApplier::Factory* const apl_factory;
 
index febad481b51481657c41c131682e73e9368769a6..1a7632431153c896c660768a9e7fee9e29bdfd7d 100644 (file)
@@ -525,7 +525,7 @@ ExternalTokenEngine::authenticate(const DoutPrefixProvider* dpp,
   auto apl = apl_factory->create_apl_local(
       cct, s, std::move(user), std::move(account),
       std::move(policies), extract_swift_subuser(swift_user),
-      std::nullopt, LocalApplier::NO_ACCESS_KEY);
+      std::nullopt, LocalApplier::NO_ACCESS_KEY, false /* is_impersonating */);
   return result_t::grant(std::move(apl));
 }
 
@@ -688,7 +688,7 @@ SignedTokenEngine::authenticate(const DoutPrefixProvider* dpp,
   auto apl = apl_factory->create_apl_local(
       cct, s, std::move(user), std::move(account),
       std::move(policies), extract_swift_subuser(swift_user),
-      std::nullopt, LocalApplier::NO_ACCESS_KEY);
+      std::nullopt, LocalApplier::NO_ACCESS_KEY, false /* is_impersonating */);
   return result_t::grant(std::move(apl));
 }
 
index c27a24a2619f598fdf75c454f96cd1396a28035d..eb34984398ca19291b9f0fd3f6327735576c5d69 100644 (file)
@@ -243,12 +243,13 @@ class DefaultStrategy : public rgw::auth::Strategy,
                             std::vector<IAM::Policy> policies,
                             const std::string& subuser,
                             const std::optional<uint32_t>& perm_mask,
-                            const std::string& access_key_id) const override {
+                            const std::string& access_key_id,
+                            bool is_impersonating) const override {
     auto apl = \
       rgw::auth::add_3rdparty(driver, rgw_user(s->account_name),
         rgw::auth::add_sysreq(cct, driver, s,
           LocalApplier(cct, std::move(user), std::move(account), std::move(policies),
-                       subuser, perm_mask, access_key_id)));
+                       subuser, perm_mask, access_key_id), is_impersonating));
     /* TODO(rzarzynski): replace with static_ptr. */
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }