]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw/auth: auth engines pass optional account info into identities
authorCasey Bodley <cbodley@redhat.com>
Thu, 29 Feb 2024 15:56:21 +0000 (10:56 -0500)
committerCasey Bodley <cbodley@redhat.com>
Fri, 12 Apr 2024 19:34:29 +0000 (15:34 -0400)
the auth identities need the RGWAccountInfo instead of just the account
id so they can fill in the correct ACLOwner::display_name

this also adds account ownership support to WebIdentityApplier for
AssumeRoleWithWebIdentity

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

13 files changed:
src/rgw/driver/rados/rgw_data_sync.cc
src/rgw/rgw_auth.cc
src/rgw/rgw_auth.h
src/rgw/rgw_auth_s3.h
src/rgw/rgw_lib.cc
src/rgw/rgw_lib.h
src/rgw/rgw_process.cc
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_rest_sts.cc
src/rgw/rgw_rest_sts.h
src/rgw/rgw_rest_swift.cc
src/rgw/rgw_swift_auth.cc
src/rgw/rgw_swift_auth.h

index 4e6295cc48acbcb35b6886f87cc451f1fdcb4a12..77e676c81a0185314560756a640588e011827e78 100644 (file)
@@ -2645,13 +2645,12 @@ class RGWUserPermHandler {
         return ret;
       }
 
-      info->identity = rgw::auth::transform_old_authinfo(sync_env->cct, uid,
-                                                         info->user_info.display_name,
-                                                         info->user_info.path,
-                                                         info->user_info.account_id,
-                                                         RGW_PERM_FULL_CONTROL,
-                                                         false, /* system_request? */
-                                                         info->user_info.type);
+      auto result = rgw::auth::transform_old_authinfo(
+          sync_env->dpp, null_yield, sync_env->driver, info->user_info);
+      if (!result) {
+        return result.error();
+      }
+      info->identity = std::move(result).value();
 
       map<string, bufferlist> uattrs;
 
index 8b8cce881ce79e80b9d83cc90a7d076a16d143ea..b01451f047e2442465ac2fb353ba26a3d6ad9d04 100644 (file)
@@ -5,6 +5,7 @@
 #include <string>
 #include <variant>
 
+#include "common/errno.h"
 #include "rgw_common.h"
 #include "rgw_auth.h"
 #include "rgw_quota.h"
@@ -64,78 +65,60 @@ static bool match_principal(std::string_view path,
 }
 
 static bool match_owner(const rgw_owner& owner, const rgw_user& uid,
-                        std::string_view account_id)
+                        const std::optional<RGWAccountInfo>& account)
 {
   return std::visit(fu2::overload(
       [&uid] (const rgw_user& u) { return u == uid; },
-      [&account_id] (const rgw_account_id& a) { return a == account_id; }
-      ), owner);
+      [&account] (const rgw_account_id& a) {
+        return account && a == account->id;
+      }), owner);
 }
 
-static bool match_account_or_tenant(const rgw_account_id& account_id,
+static bool match_account_or_tenant(const std::optional<RGWAccountInfo>& account,
                                     std::string_view tenant,
                                     std::string_view expected)
 {
-  if (!account_id.empty()) {
-    return account_id == expected;
-  } else {
-    return tenant == expected;
-  }
+  return (account && account->id == expected)
+      || (tenant == expected);
 }
 
-std::unique_ptr<rgw::auth::Identity>
-transform_old_authinfo(CephContext* const cct,
-                       const rgw_user& auth_id,
-                       const std::string& display_name,
-                       const std::string& path,
-                       const rgw_account_id& account_id,
-                       const int perm_mask,
-                       const bool is_admin,
-                       const uint32_t type)
+auto transform_old_authinfo(const RGWUserInfo& user,
+                            std::optional<RGWAccountInfo> account)
+  -> std::unique_ptr<rgw::auth::Identity>
 {
   /* This class is not intended for public use. Should be removed altogether
    * with this function after moving all our APIs to the new authentication
    * infrastructure. */
   class DummyIdentityApplier : public rgw::auth::Identity {
-    CephContext* const cct;
-
     /* For this particular case it's OK to use rgw_user structure to convey
      * the identity info as this was the policy for doing that before the
      * new auth. */
     const rgw_user id;
     const std::string display_name;
     const std::string path;
-    const rgw_account_id account_id;
-    const int perm_mask;
     const bool is_admin;
     const uint32_t type;
+    const std::optional<RGWAccountInfo> account;
   public:
-    DummyIdentityApplier(CephContext* const cct,
-                         const rgw_user& auth_id,
-                         const std::string display_name,
-                         const std::string path,
-                         const rgw_account_id& account_id,
-                         const int perm_mask,
-                         const bool is_admin,
-                         const uint32_t type)
-      : cct(cct),
-        id(auth_id),
-        display_name(display_name),
-        path(path),
-        account_id(account_id),
-        perm_mask(perm_mask),
-        is_admin(is_admin),
-        type(type) {
-    }
+    DummyIdentityApplier(const RGWUserInfo& user,
+                         std::optional<RGWAccountInfo> account)
+      : id(user.user_id),
+        display_name(user.display_name),
+        path(user.path),
+        is_admin(user.admin),
+        type(user.type),
+        account(std::move(account))
+    {}
 
     ACLOwner get_aclowner() const {
       ACLOwner owner;
-      if (!account_id.empty()) {
-        owner.id.emplace<rgw_account_id>(account_id);
+      if (account) {
+        owner.id = account->id;
+        owner.display_name = account->name;
       } else {
         owner.id = id;
+        owner.display_name = display_name;
       }
-      owner.display_name = display_name;
       return owner;
     }
 
@@ -148,19 +131,19 @@ transform_old_authinfo(CephContext* const cct,
     }
 
     bool is_owner_of(const rgw_owner& o) const override {
-      return match_owner(o, id, account_id);
+      return match_owner(o, id, account);
     }
 
     bool is_identity(const Principal& p) const override {
       if (p.is_wildcard()) {
         return true;
       } else if (p.is_account()) {
-        return match_account_or_tenant(account_id, id.tenant,
+        return match_account_or_tenant(account, id.tenant,
                                        p.get_account());
       } else if (p.is_user()) {
         std::string_view no_subuser;
         // account users can match both account- and tenant-based arns
-        if (!account_id.empty() && p.get_account() == account_id) {
+        if (account && p.get_account() == account->id) {
           return match_principal(path, display_name, no_subuser, p.get_id());
         } else {
           return p.get_account() == id.tenant
@@ -171,7 +154,7 @@ transform_old_authinfo(CephContext* const cct,
     }
 
     uint32_t get_perm_mask() const override {
-      return perm_mask;
+      return RGW_PERM_FULL_CONTROL;
     }
 
     uint32_t get_identity_type() const override {
@@ -191,30 +174,35 @@ transform_old_authinfo(CephContext* const cct,
 
     void to_str(std::ostream& out) const override {
       out << "RGWDummyIdentityApplier(auth_id=" << id
-          << ", perm_mask=" << perm_mask
           << ", is_admin=" << is_admin << ")";
     }
   };
 
-  return std::make_unique<DummyIdentityApplier>(
-      cct, auth_id, display_name, path, account_id,
-      perm_mask, is_admin, type);
+  return std::make_unique<DummyIdentityApplier>(user, std::move(account));
 }
 
-std::unique_ptr<rgw::auth::Identity>
-transform_old_authinfo(const req_state* const s)
+auto transform_old_authinfo(const DoutPrefixProvider* dpp,
+                            optional_yield y,
+                            rgw::sal::Driver* driver,
+                            const RGWUserInfo& user)
+  -> tl::expected<std::unique_ptr<Identity>, int>
 {
-  const RGWUserInfo& info = s->user->get_info();
-  return transform_old_authinfo(s->cct,
-                                info.user_id,
-                                info.display_name,
-                                info.path,
-                                info.account_id,
-                                s->perm_mask,
-  /* System user has admin permissions by default - it's supposed to pass
-   * through any security check. */
-                                s->system_request,
-                                info.type);
+  std::optional<RGWAccountInfo> account;
+  if (!user.account_id.empty()) {
+    account.emplace();
+    rgw::sal::Attrs attrs; // ignored
+    RGWObjVersionTracker objv; // ignored
+    int r = driver->load_account_by_id(dpp, y, user.account_id,
+                                       *account, attrs, objv);
+    if (r < 0) {
+      ldpp_dout(dpp, 1) << "ERROR: failed to load account "
+          << user.account_id << " for user " << user.user_id
+          << ": " << cpp_strerror(r) << dendl;
+      return tl::unexpected(r);
+    }
+  }
+
+  return transform_old_authinfo(user, std::move(account));
 }
 
 } /* namespace auth */
@@ -454,10 +442,29 @@ rgw::auth::Strategy::add_engine(const Control ctrl_flag,
   auth_stack.push_back(std::make_pair(std::cref(engine), ctrl_flag));
 }
 
+ACLOwner rgw::auth::WebIdentityApplier::get_aclowner() const
+{
+  ACLOwner owner;
+  if (account) {
+    owner.id = account->id;
+    owner.display_name = account->name;
+  } else {
+    owner.id = rgw_user{role_tenant, sub, "oidc"};
+    owner.display_name = user_name;
+  }
+  return owner;
+}
+
+bool rgw::auth::WebIdentityApplier::is_owner_of(const rgw_owner& o) const
+{
+  return match_owner(o, rgw_user{role_tenant, sub, "oidc"}, account);
+}
+
 void rgw::auth::WebIdentityApplier::to_str(std::ostream& out) const
 {
   out << "rgw::auth::WebIdentityApplier(sub =" << sub
       << ", user_name=" << user_name
+      << ", role_id=" << role_id
       << ", provider_id =" << iss << ")";
 }
 
@@ -619,6 +626,7 @@ const std::string rgw::auth::RemoteApplier::AuthInfo::NO_ACCESS_KEY;
 ACLOwner rgw::auth::RemoteApplier::get_aclowner() const
 {
   ACLOwner owner;
+  // TODO: handle account ownership
   owner.id = info.acct_user;
   owner.display_name = info.acct_name;
   return owner;
@@ -843,12 +851,13 @@ const std::string rgw::auth::LocalApplier::NO_ACCESS_KEY;
 ACLOwner rgw::auth::LocalApplier::get_aclowner() const
 {
   ACLOwner owner;
-  if (!user_info.account_id.empty()) {
-    owner.id = user_info.account_id;
+  if (account) {
+    owner.id = account->id;
+    owner.display_name = account->name;
   } else {
     owner.id = user_info.user_id;
+    owner.display_name = user_info.display_name;
   }
-  owner.display_name = user_info.display_name;
   return owner;
 }
 
@@ -858,12 +867,11 @@ uint32_t rgw::auth::LocalApplier::get_perms_from_aclspec(const DoutPrefixProvide
   uint32_t mask = rgw_perms_from_aclspec_default_strategy(
       user_info.user_id.to_str(), aclspec, dpp);
 
-  if (!user_info.account_id.empty()) {
+  if (account) {
     // account users also match acl grants to the account id. in aws, grantees
     // ONLY refer to accounts. but we continue to match user grants to preserve
     // access when moving legacy users into new accounts
-    mask |= rgw_perms_from_aclspec_default_strategy(
-        user_info.account_id, aclspec, dpp);
+    mask |= rgw_perms_from_aclspec_default_strategy(account->id, aclspec, dpp);
   }
 
   return mask;
@@ -876,20 +884,18 @@ bool rgw::auth::LocalApplier::is_admin_of(const rgw_owner& o) const
 
 bool rgw::auth::LocalApplier::is_owner_of(const rgw_owner& o) const
 {
-  return match_owner(o, user_info.user_id, user_info.account_id);
+  return match_owner(o, user_info.user_id, account);
 }
 
 bool rgw::auth::LocalApplier::is_identity(const Principal& p) const {
   if (p.is_wildcard()) {
     return true;
   } else if (p.is_account()) {
-    return match_account_or_tenant(user_info.account_id,
-                                   user_info.user_id.tenant,
+    return match_account_or_tenant(account, user_info.user_id.tenant,
                                    p.get_account());
   } else if (p.is_user()) {
     // account users can match both account- and tenant-based arns
-    if (!user_info.account_id.empty() &&
-        p.get_account() == user_info.account_id) {
+    if (account && p.get_account() == account->id) {
       return match_principal(user_info.path, user_info.display_name,
                              subuser, p.get_id());
     } else {
@@ -943,18 +949,19 @@ void rgw::auth::LocalApplier::write_ops_log_entry(rgw_log_entry& entry) const
 ACLOwner rgw::auth::RoleApplier::get_aclowner() const
 {
   ACLOwner owner;
-  if (!role.account_id.empty()) {
-    owner.id = role.account_id;
+  if (role.account) {
+    owner.id = role.account->id;
+    owner.display_name = role.account->name;
   } else {
     owner.id = token_attrs.user_id;
+    owner.display_name = role.name;
   }
-  owner.display_name = role.name;
   return owner;
 }
 
 bool rgw::auth::RoleApplier::is_owner_of(const rgw_owner& o) const
 {
-  return match_owner(o, token_attrs.user_id, role.account_id);
+  return match_owner(o, token_attrs.user_id, role.account);
 }
 
 void rgw::auth::RoleApplier::to_str(std::ostream& out) const {
@@ -977,12 +984,12 @@ bool rgw::auth::RoleApplier::is_identity(const Principal& p) const {
   if (p.is_wildcard()) {
     return true;
   } else if (p.is_account()) {
-    return match_account_or_tenant(role.account_id, role.tenant,
+    return match_account_or_tenant(role.account, role.tenant,
                                    p.get_account());
   } else if (p.is_role()) {
     std::string_view no_subuser;
     // account roles can match both account- and tenant-based arns
-    return match_account_or_tenant(role.account_id, role.tenant, p.get_account())
+    return match_account_or_tenant(role.account, role.tenant, p.get_account())
         && match_principal(role.path, role.name, no_subuser, p.get_id());
   } else if (p.is_assumed_role()) {
     string role_session = role.name + "/" + token_attrs.role_session_name; //role/role-session
@@ -1010,7 +1017,7 @@ void rgw::auth::RoleApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUs
 void rgw::auth::RoleApplier::modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const
 {
   // non-account identity policy is restricted to the current tenant
-  const std::string* policy_tenant = role.account_id.empty() ? &role.tenant : nullptr;
+  const std::string* policy_tenant = role.account ? nullptr : &role.tenant;
 
   for (const auto& policy : role.inline_policies) {
     try {
@@ -1079,7 +1086,7 @@ rgw::auth::AnonymousEngine::authenticate(const DoutPrefixProvider* dpp, const re
     rgw_get_anon_user(user_info);
 
     auto apl = \
-      apl_factory->create_apl_local(cct, s, user_info,
+      apl_factory->create_apl_local(cct, s, user_info, std::nullopt,
                                     rgw::auth::LocalApplier::NO_SUBUSER,
                                     std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
     return result_t::grant(std::move(apl));
index 64e55d532f0613a4f46cb2e7f095a995004ca052..0e7eabe0c9fddf728a74c0065d6311465557d27f 100644 (file)
@@ -10,6 +10,7 @@
 #include <system_error>
 #include <utility>
 
+#include "include/expected.hpp"
 #include "include/function2.hpp"
 
 #include "rgw_common.h"
@@ -97,16 +98,17 @@ inline std::ostream& operator<<(std::ostream& out,
 }
 
 
-std::unique_ptr<rgw::auth::Identity>
-transform_old_authinfo(CephContext* const cct,
-                       const rgw_user& auth_id,
-                       const std::string& display_name,
-                       const std::string& path,
-                       const rgw_account_id& account_id,
-                       const int perm_mask,
-                       const bool is_admin,
-                       const uint32_t type);
-std::unique_ptr<Identity> transform_old_authinfo(const req_state* const s);
+// Return an identity for the given user and account.
+auto transform_old_authinfo(const RGWUserInfo& user,
+                            std::optional<RGWAccountInfo> account)
+  -> std::unique_ptr<rgw::auth::Identity>;
+
+// Return an identity for the given user, loading its account if necessary.
+auto transform_old_authinfo(const DoutPrefixProvider* dpp,
+                            optional_yield y,
+                            rgw::sal::Driver* driver,
+                            const RGWUserInfo& user)
+  -> tl::expected<std::unique_ptr<Identity>, int>;
 
 
 /* Interface for classes applying changes to request state/RADOS store
@@ -382,11 +384,13 @@ class WebIdentityApplier : public IdentityApplier {
 protected:
   CephContext* const cct;
   rgw::sal::Driver* driver;
+  std::string role_id;
   std::string role_session;
   std::string role_tenant;
   std::unordered_multimap<std::string, std::string> token_claims;
   boost::optional<std::multimap<std::string,std::string>> role_tags;
   boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags;
+  std::optional<RGWAccountInfo> account;
 
   std::string get_idp_url() const;
 
@@ -397,18 +401,23 @@ protected:
 public:
   WebIdentityApplier( CephContext* const cct,
                       rgw::sal::Driver* driver,
+                      const std::string& role_id,
                       const std::string& role_session,
                       const std::string& role_tenant,
                       const std::unordered_multimap<std::string, std::string>& token_claims,
                       boost::optional<std::multimap<std::string,std::string>> role_tags,
-                      boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags)
+                      boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags,
+                      std::optional<RGWAccountInfo> account)
       : cct(cct),
       driver(driver),
+      role_id(role_id),
       role_session(role_session),
       role_tenant(role_tenant),
       token_claims(token_claims),
       role_tags(role_tags),
-      principal_tags(principal_tags) {
+      principal_tags(principal_tags),
+      account(std::move(account))
+  {
       const auto& sub = token_claims.find("sub");
       if(sub != token_claims.end()) {
         this->sub = sub->second;
@@ -447,12 +456,7 @@ public:
 
   void modify_request_state(const DoutPrefixProvider *dpp, req_state* s) const override;
 
-  ACLOwner get_aclowner() const override {
-    ACLOwner owner;
-    owner.id = rgw_user{role_tenant, sub, "oidc"};
-    owner.display_name = user_name;
-    return owner;
-  }
+  ACLOwner get_aclowner() const override;
 
   uint32_t get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const  override {
     return RGW_PERM_NONE;
@@ -462,10 +466,7 @@ public:
     return false;
   }
 
-  bool is_owner_of(const rgw_owner& o) const override {
-    auto* uid = std::get_if<rgw_user>(&o);
-    return uid && uid->id == sub && uid->tenant == role_tenant && uid->ns == "oidc";
-  }
+  bool is_owner_of(const rgw_owner& o) const override;
 
   uint32_t get_perm_mask() const override {
     return RGW_PERM_NONE;
@@ -497,11 +498,13 @@ public:
 
     virtual aplptr_t create_apl_web_identity( CephContext* cct,
                                               const req_state* s,
+                                              const std::string& role_id,
                                               const std::string& role_session,
                                               const std::string& role_tenant,
                                               const std::unordered_multimap<std::string, std::string>& token,
                                               boost::optional<std::multimap<std::string, std::string>>,
-                                              boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags) const = 0;
+                                              boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags,
+                                              std::optional<RGWAccountInfo> account) const = 0;
   };
 };
 
@@ -665,6 +668,7 @@ class LocalApplier : public IdentityApplier {
 
 protected:
   const RGWUserInfo user_info;
+  const std::optional<RGWAccountInfo> account;
   const std::string subuser;
   uint32_t perm_mask;
   const std::string access_key_id;
@@ -678,10 +682,12 @@ public:
 
   LocalApplier(CephContext* const cct,
                const RGWUserInfo& user_info,
+               std::optional<RGWAccountInfo> account,
                std::string subuser,
                const std::optional<uint32_t>& perm_mask,
                const std::string access_key_id)
     : user_info(user_info),
+      account(std::move(account)),
       subuser(std::move(subuser)),
       perm_mask(perm_mask.value_or(RGW_PERM_INVALID)),
       access_key_id(access_key_id) {
@@ -715,6 +721,7 @@ public:
     virtual aplptr_t create_apl_local(CephContext* cct,
                                       const req_state* s,
                                       const RGWUserInfo& user_info,
+                                      std::optional<RGWAccountInfo> account,
                                       const std::string& subuser,
                                       const std::optional<uint32_t>& perm_mask,
                                       const std::string& access_key_id) const = 0;
@@ -728,7 +735,7 @@ public:
     std::string name;
     std::string path;
     std::string tenant;
-    rgw_account_id account_id;
+    std::optional<RGWAccountInfo> account;
     std::vector<std::string> inline_policies;
     std::vector<std::string> managed_policies;
   };
@@ -775,11 +782,11 @@ public:
 
   struct Factory {
     virtual ~Factory() {}
-    virtual aplptr_t create_apl_role( CephContext* cct,
-                                      const req_state* s,
-                                      const rgw::auth::RoleApplier::Role& role,
-                                      const rgw::auth::RoleApplier::TokenAttrs& token_attrs) const = 0;
-    };
+    virtual aplptr_t create_apl_role(CephContext* cct,
+                                     const req_state* s,
+                                     Role role,
+                                     TokenAttrs token_attrs) const = 0;
+  };
 };
 
 /* The anonymous abstract engine. */
index b2b1238f3130144aa108a30d38d9e2865018af2c..c7cde7c04969df4975ac545b7f117cf749c806bf 100644 (file)
@@ -56,20 +56,22 @@ class STSAuthStrategy : public rgw::auth::Strategy,
   aplptr_t create_apl_local(CephContext* const cct,
                             const req_state* const s,
                             const RGWUserInfo& user_info,
+                            std::optional<RGWAccountInfo> account,
                             const std::string& subuser,
                             const std::optional<uint32_t>& perm_mask,
                             const std::string& access_key_id) const override {
     auto apl = rgw::auth::add_sysreq(cct, driver, s,
-      rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask, access_key_id));
+      rgw::auth::LocalApplier(cct, user_info, std::move(account),
+                              subuser, perm_mask, access_key_id));
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
 
   aplptr_t create_apl_role(CephContext* const cct,
                             const req_state* const s,
-                            const rgw::auth::RoleApplier::Role& role,
-                            const rgw::auth::RoleApplier::TokenAttrs& token_attrs) const override {
+                            RoleApplier::Role role,
+                            RoleApplier::TokenAttrs token_attrs) const override {
     auto apl = rgw::auth::add_sysreq(cct, driver, s,
-      rgw::auth::RoleApplier(cct, role, token_attrs));
+      rgw::auth::RoleApplier(cct, std::move(role), std::move(token_attrs)));
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
 
@@ -113,8 +115,8 @@ class ExternalAuthStrategy : public rgw::auth::Strategy,
                              rgw::auth::RemoteApplier::acl_strategy_t&& acl_alg,
                              const rgw::auth::RemoteApplier::AuthInfo &info) const override {
     auto apl = rgw::auth::add_sysreq(cct, driver, s,
-      rgw::auth::RemoteApplier(cct, driver, std::move(acl_alg), info,
-                               implicit_tenant_context,
+      rgw::auth::RemoteApplier(cct, driver, std::move(acl_alg),
+                               info, implicit_tenant_context,
                                rgw::auth::ImplicitTenants::IMPLICIT_TENANTS_S3));
     /* TODO(rzarzynski): replace with static_ptr. */
     return aplptr_t(new decltype(apl)(std::move(apl)));
@@ -174,11 +176,13 @@ class AWSAuthStrategy : public rgw::auth::Strategy,
   aplptr_t create_apl_local(CephContext* const cct,
                             const req_state* const s,
                             const RGWUserInfo& user_info,
+                            std::optional<RGWAccountInfo> account,
                             const std::string& subuser,
                             const std::optional<uint32_t>& perm_mask,
                             const std::string& access_key_id) const override {
     auto apl = rgw::auth::add_sysreq(cct, driver, s,
-      rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask, access_key_id));
+      rgw::auth::LocalApplier(cct, user_info, std::move(account),
+                              subuser, perm_mask, access_key_id));
     /* TODO(rzarzynski): replace with static_ptr. */
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
index 5a8fc14a80471cb4db74b5f6855bc6db6132de62..85763e1a2671cd72e10aa72d733f070a8b99d256 100644 (file)
@@ -247,7 +247,8 @@ namespace rgw {
       /* FIXME: remove this after switching all handlers to the new
        * authentication infrastructure. */
       if (! s->auth.identity) {
-       s->auth.identity = rgw::auth::transform_old_authinfo(s);
+       s->auth.identity = rgw::auth::transform_old_authinfo(
+            io->get_user(), std::nullopt);
       }
 
       ldpp_dout(s, 2) << "reading op permissions" << dendl;
@@ -377,7 +378,8 @@ namespace rgw {
     /* FIXME: remove this after switching all handlers to the new authentication
      * infrastructure. */
     if (! s->auth.identity) {
-      s->auth.identity = rgw::auth::transform_old_authinfo(s);
+      s->auth.identity = rgw::auth::transform_old_authinfo(
+          io_ctx.get_user(), std::nullopt);
     }
 
     ldpp_dout(s, 2) << "reading op permissions" << dendl;
@@ -563,9 +565,10 @@ namespace rgw {
     if (ret < 0) {
       derr << "ERROR: failed reading user info: uid=" << uid << " ret="
           << ret << dendl;
+      return ret;
     }
     user_info = user->get_info();
-    return ret;
+    return 0;
   }
 
   int RGWLibRequest::read_permissions(RGWOp* op, optional_yield y) {
index 30234eebcdd332f6383d50b0170d70dc21c3533c..643e0c2c2d24ce0f54beb800249432fbbee921ba 100644 (file)
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <mutex>
+#include <optional>
 #include "rgw_common.h"
 #include "rgw_client_io.h"
 #include "rgw_rest.h"
index 1765e83d62244de8e611a54ce395cb6d90fff750..7a7f70fa30d8448ef24a93485d60273b7600ed1b 100644 (file)
@@ -366,7 +366,13 @@ int process_request(const RGWProcessEnv& penv,
     /* FIXME: remove this after switching all handlers to the new authentication
      * infrastructure. */
     if (nullptr == s->auth.identity) {
-      s->auth.identity = rgw::auth::transform_old_authinfo(s);
+      auto result = rgw::auth::transform_old_authinfo(
+          op, yield, driver, s->user->get_info());
+      if (!result) {
+        abort_early(s, op, result.error(), handler, yield);
+        goto done;
+      }
+      s->auth.identity = std::move(result).value();
     }
 
     ldpp_dout(op, 2) << "normalizing buckets and tenants" << dendl;
index 073b9bf9013f852cac8fb083c24aaec1edbf3688..391953219ae5790f9e61c624b3bc2bd139b4bcbe 100644 (file)
@@ -6280,6 +6280,21 @@ rgw::auth::s3::LocalEngine::authenticate(
     }
   }*/
 
+  std::optional<RGWAccountInfo> account;
+  if (!user->get_info().account_id.empty()) {
+    account.emplace();
+    rgw::sal::Attrs attrs; // ignored
+    RGWObjVersionTracker objv; // ignored
+    int r = driver->load_account_by_id(dpp, y, user->get_info().account_id,
+                                       *account, attrs, objv);
+    if (r < 0) {
+      ldpp_dout(dpp, 1) << "ERROR: failed to load account "
+          << user->get_info().account_id << " for user " << *user
+          << ": " << cpp_strerror(r) << dendl;
+      return result_t::deny(-EPERM);
+    }
+  }
+
   const auto iter = user->get_info().access_keys.find(access_key_id);
   if (iter == std::end(user->get_info().access_keys)) {
     ldpp_dout(dpp, 0) << "ERROR: access key not encoded in user info" << dendl;
@@ -6289,7 +6304,7 @@ rgw::auth::s3::LocalEngine::authenticate(
 
   /* Ignore signature for HTTP OPTIONS */
   if (s->op_type == RGW_OP_OPTIONS_CORS) {
-    auto apl = apl_factory->create_apl_local(cct, s, user->get_info(),
+    auto apl = apl_factory->create_apl_local(cct, s, user->get_info(), std::move(account),
                                              k.subuser, std::nullopt, access_key_id);
     return result_t::grant(std::move(apl), completer_factory(k.key));
   }
@@ -6309,7 +6324,7 @@ rgw::auth::s3::LocalEngine::authenticate(
     return result_t::reject(-ERR_SIGNATURE_NO_MATCH);
   }
 
-  auto apl = apl_factory->create_apl_local(cct, s, user->get_info(),
+  auto apl = apl_factory->create_apl_local(cct, s, user->get_info(), std::move(account),
                                            k.subuser, std::nullopt, access_key_id);
   return result_t::grant(std::move(apl), completer_factory(k.key));
 }
@@ -6444,7 +6459,6 @@ rgw::auth::s3::STSEngine::authenticate(
   }
 
   // Get all the authorization info
-  std::unique_ptr<rgw::sal::User> user;
   rgw_user user_id;
   string role_id;
   rgw::auth::RoleApplier::Role r;
@@ -6458,7 +6472,21 @@ rgw::auth::s3::STSEngine::authenticate(
     r.name = role->get_name();
     r.path = role->get_path();
     r.tenant = role->get_tenant();
-    r.account_id = role->get_account_id();
+
+    const auto& account_id = role->get_account_id();
+    if (!account_id.empty()) {
+      r.account.emplace();
+      rgw::sal::Attrs attrs; // ignored
+      RGWObjVersionTracker objv; // ignored
+      int ret = driver->load_account_by_id(dpp, y, account_id,
+                                           *r.account, attrs, objv);
+      if (ret < 0) {
+        ldpp_dout(dpp, 1) << "ERROR: failed to load account "
+            << account_id << " for role " << r.name
+            << ": " << cpp_strerror(ret) << dendl;
+        return result_t::deny(-EPERM);
+      }
+    }
 
     for (auto& [name, policy] : role->get_info().perm_policy_map) {
       r.inline_policies.push_back(std::move(policy));
@@ -6468,16 +6496,6 @@ rgw::auth::s3::STSEngine::authenticate(
     }
   }
 
-  user = driver->get_user(token.user);
-  if (! token.user.empty() && token.acct_type != TYPE_ROLE) {
-    // get user info
-    int ret = user->load_user(dpp, y);
-    if (ret < 0) {
-      ldpp_dout(dpp, 5) << "ERROR: failed reading user info: uid=" << token.user << dendl;
-      return result_t::reject(-EPERM);
-    }
-  }
-
   if (token.acct_type == TYPE_KEYSTONE || token.acct_type == TYPE_LDAP) {
     auto apl = remote_apl_factory->create_apl_remote(cct, s, get_acl_strategy(),
                                             get_creds_info(token));
@@ -6489,11 +6507,41 @@ rgw::auth::s3::STSEngine::authenticate(
     t_attrs.token_claims = std::move(token.token_claims);
     t_attrs.token_issued_at = std::move(token.issued_at);
     t_attrs.principal_tags = std::move(token.principal_tags);
-    auto apl = role_apl_factory->create_apl_role(cct, s, r, t_attrs);
+    auto apl = role_apl_factory->create_apl_role(cct, s, std::move(r),
+                                                 std::move(t_attrs));
     return result_t::grant(std::move(apl), completer_factory(token.secret_access_key));
   } else { // This is for all local users of type TYPE_RGW|ROOT|NONE
+    if (token.user.empty()) {
+      ldpp_dout(dpp, 5) << "ERROR: got session token with empty user id" << dendl;
+      return result_t::reject(-EPERM);
+    }
+    // load user info
+    auto user = driver->get_user(token.user);
+    int ret = user->load_user(dpp, y);
+    if (ret < 0) {
+      ldpp_dout(dpp, 5) << "ERROR: failed reading user info: uid=" << token.user << dendl;
+      return result_t::reject(-EPERM);
+    }
+
+    std::optional<RGWAccountInfo> account;
+    if (!user->get_info().account_id.empty()) {
+      account.emplace();
+      rgw::sal::Attrs attrs; // ignored
+      RGWObjVersionTracker objv; // ignored
+      int r = driver->load_account_by_id(dpp, y, user->get_info().account_id,
+                                         *account, attrs, objv);
+      if (r < 0) {
+        ldpp_dout(dpp, 1) << "ERROR: failed to load account "
+            << user->get_info().account_id << " for user " << *user
+            << ": " << cpp_strerror(r) << dendl;
+        return result_t::deny(-EPERM);
+      }
+    }
+
     string subuser;
-    auto apl = local_apl_factory->create_apl_local(cct, s, user->get_info(), subuser, token.perm_mask, std::string(_access_key_id));
+    auto apl = local_apl_factory->create_apl_local(cct, s, user->get_info(),
+                                                   std::move(account), subuser,
+                                                   token.perm_mask, std::string(_access_key_id));
     return result_t::grant(std::move(apl), completer_factory(token.secret_access_key));
   }
 }
index cbb1b7de1180d7214146c8665accf0b81d7e4ba4..b9c23aa159c2665e3066cf74d5270fd501bbf6b3 100644 (file)
@@ -502,8 +502,24 @@ WebTokenEngine::authenticate( const DoutPrefixProvider* dpp,
         ldpp_dout(dpp, 0) << "Role not found: name:" << role_name << " tenant: " << role_tenant << dendl;
         return result_t::deny(-EACCES);
       }
+
+      std::optional<RGWAccountInfo> account;
+      if (!role_account.empty()) {
+        account.emplace();
+        rgw::sal::Attrs attrs; // ignored
+        RGWObjVersionTracker objv; // ignored
+        ret = driver->load_account_by_id(dpp, y, role_account,
+                                         *account, attrs, objv);
+        if (ret < 0) {
+          ldpp_dout(dpp, 0) << "Role account " << role_account << " not found" << dendl;
+          return result_t::deny(-EACCES);
+        }
+      }
+
       boost::optional<multimap<string,string>> role_tags = role->get_tags();
-      auto apl = apl_factory->create_apl_web_identity(cct, s, role_session, role->get_tenant(), *t, role_tags, princ_tags);
+      auto apl = apl_factory->create_apl_web_identity(
+          cct, s, role->get_id(), role_session, role_tenant,
+          *t, role_tags, princ_tags, std::move(account));
       return result_t::grant(std::move(apl));
     }
     return result_t::deny(-EACCES);
index aa66972943995acd9102373f78441cfeaeac2965..432244009202f7b32683b74a67b518051362db3c 100644 (file)
@@ -101,13 +101,17 @@ class DefaultStrategy : public rgw::auth::Strategy,
 
   aplptr_t create_apl_web_identity( CephContext* cct,
                                     const req_state* s,
+                                    const std::string& role_id,
                                     const std::string& role_session,
                                     const std::string& role_tenant,
                                     const std::unordered_multimap<std::string, std::string>& token,
                                     boost::optional<std::multimap<std::string, std::string>> role_tags,
-                                    boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags) const override {
+                                    boost::optional<std::set<std::pair<std::string, std::string>>> principal_tags,
+                                    std::optional<RGWAccountInfo> account) const override {
     auto apl = rgw::auth::add_sysreq(cct, driver, s,
-      rgw::auth::WebIdentityApplier(cct, driver, role_session, role_tenant, token, role_tags, principal_tags));
+      rgw::auth::WebIdentityApplier(cct, driver, role_id, role_session,
+                                    role_tenant, token, role_tags,
+                                    principal_tags, std::move(account)));
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
 
index fe366acf8563a27b8be037540af58758a6d7c5b2..129726f0584f86022ac1e0ae55923bd02a7e87ac 100644 (file)
@@ -2138,7 +2138,8 @@ bool RGWFormPost::is_integral()
 
   try {
     get_owner_info(s, s->user->get_info());
-    s->auth.identity = rgw::auth::transform_old_authinfo(s);
+    s->auth.identity = rgw::auth::transform_old_authinfo(
+        s->user->get_info(), std::nullopt);
   } catch (...) {
     ldpp_dout(this, 5) << "cannot get user_info of account's owner" << dendl;
     return false;
index 9edf257b6b80bf2baba66c2f279f88cb4d6a74e2..f191d3628af99371a52bab80c798277483e5bc4e 100644 (file)
@@ -513,7 +513,23 @@ ExternalTokenEngine::authenticate(const DoutPrefixProvider* dpp,
     throw ret;
   }
 
+  std::optional<RGWAccountInfo> account;
+  if (!user->get_info().account_id.empty()) {
+    account.emplace();
+    rgw::sal::Attrs attrs; // ignored
+    RGWObjVersionTracker objv; // ignored
+    int r = driver->load_account_by_id(dpp, y, user->get_info().account_id,
+                                       *account, attrs, objv);
+    if (r < 0) {
+      ldpp_dout(dpp, 1) << "ERROR: failed to load account "
+          << user->get_info().account_id << " for user " << *user
+          << ": " << cpp_strerror(r) << dendl;
+      return result_t::deny(-EPERM);
+    }
+  }
+
   auto apl = apl_factory->create_apl_local(cct, s, user->get_info(),
+                                           std::move(account),
                                            extract_swift_subuser(swift_user),
                                            std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
   return result_t::grant(std::move(apl));
@@ -633,6 +649,21 @@ SignedTokenEngine::authenticate(const DoutPrefixProvider* dpp,
     throw ret;
   }
 
+  std::optional<RGWAccountInfo> account;
+  if (!user->get_info().account_id.empty()) {
+    account.emplace();
+    rgw::sal::Attrs attrs; // ignored
+    RGWObjVersionTracker objv; // ignored
+    int r = driver->load_account_by_id(dpp, s->yield, user->get_info().account_id,
+                                       *account, attrs, objv);
+    if (r < 0) {
+      ldpp_dout(dpp, 1) << "ERROR: failed to load account "
+          << user->get_info().account_id << " for user " << *user
+          << ": " << cpp_strerror(r) << dendl;
+      return result_t::deny(-EPERM);
+    }
+  }
+
   ldpp_dout(dpp, 10) << "swift_user=" << swift_user << dendl;
 
   const auto siter = user->get_info().swift_keys.find(swift_user);
@@ -668,6 +699,7 @@ SignedTokenEngine::authenticate(const DoutPrefixProvider* dpp,
   }
 
   auto apl = apl_factory->create_apl_local(cct, s, user->get_info(),
+                                           std::move(account),
                                            extract_swift_subuser(swift_user),
                                            std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
   return result_t::grant(std::move(apl));
index 1c72a9472f65fd80127d219f82f256a3979a9ca3..c5435556fd2a734fb3a46a8420c50cb6f2e0cbfa 100644 (file)
@@ -24,8 +24,9 @@ class TempURLApplier : public rgw::auth::LocalApplier {
 public:
   TempURLApplier(CephContext* const cct,
                  const RGWUserInfo& user_info)
-    : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, std::nullopt, LocalApplier::NO_ACCESS_KEY) {
-  };
+    : LocalApplier(cct, user_info, std::nullopt, LocalApplier::NO_SUBUSER,
+                   std::nullopt, LocalApplier::NO_ACCESS_KEY)
+  {}
 
   void modify_request_state(const DoutPrefixProvider* dpp, req_state * s) const override; /* in/out */
   void write_ops_log_entry(rgw_log_entry& entry) const override;
@@ -155,7 +156,8 @@ class SwiftAnonymousApplier : public rgw::auth::LocalApplier {
   public:
     SwiftAnonymousApplier(CephContext* const cct,
                           const RGWUserInfo& user_info)
-      : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, std::nullopt, LocalApplier::NO_ACCESS_KEY) {
+      : LocalApplier(cct, user_info, std::nullopt, LocalApplier::NO_SUBUSER,
+                     std::nullopt, LocalApplier::NO_ACCESS_KEY) {
     }
     bool is_admin_of(const rgw_owner& o) const {return false;}
     bool is_owner_of(const rgw_owner& o) const {
@@ -237,13 +239,15 @@ class DefaultStrategy : public rgw::auth::Strategy,
   aplptr_t create_apl_local(CephContext* const cct,
                             const req_state* const s,
                             const RGWUserInfo& user_info,
+                            std::optional<RGWAccountInfo> account,
                             const std::string& subuser,
                             const std::optional<uint32_t>& perm_mask,
                             const std::string& access_key_id) const override {
     auto apl = \
       rgw::auth::add_3rdparty(driver, rgw_user(s->account_name),
         rgw::auth::add_sysreq(cct, driver, s,
-          rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask, access_key_id)));
+          rgw::auth::LocalApplier(cct, user_info, std::move(account),
+                                  subuser, perm_mask, access_key_id)));
     /* TODO(rzarzynski): replace with static_ptr. */
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }