]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: log identity applier metadata in ops logs 46622/head
authorCory Snyder <csnyder@iland.com>
Wed, 1 Jun 2022 09:04:24 +0000 (05:04 -0400)
committerCory Snyder <csnyder@iland.com>
Fri, 10 Jun 2022 14:45:28 +0000 (10:45 -0400)
As relevant, logs the access key id, subuser, and whether a request was made
via a temp_url in the ops logs for auditing purposes.

Fixes: https://tracker.ceph.com/issues/53367
Signed-off-by: Cory Snyder <csnyder@iland.com>
(cherry picked from commit ebf4209fa74e6cfa56aa364e8164304b86fca0b3)

Conflicts:
src/rgw/rgw_auth.cc
src/rgw/rgw_auth.h
src/rgw/rgw_auth_s3.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_swift_auth.cc
src/rgw/rgw_swift_auth.h

Cherry-pick notes:

rgw_auth.h:
- get_role_tenant, get_acct_name, get_subuser return non-qualified string in Pacific
- LocalApplier constructor uses boost::optional for perm_mask in Pacific
- create_apl_local uses boost::optional for perm_mask in Pacific
rgw_auth.cc:
- AnonymousEngine::authenticate call to apl_factory->create_apl_local takes boost::none in Pacific
rgw_auth_s3.h:
- create_apl_remote formatting different in Pacific
- create_apl_local uses boost::optional for perm_mask in Pacific
rgw_rest_s3.cc:
- LocalEngine::authenticate call to apl_factory->create_apl_local takes boost::none in Pacific
- STSEngine::authenticate call to apl_factory->create_apl_local takes boost::none in Pacific
rgw_swift_auth.cc:
- ExternalTokenEngine::authenticate call to apl_factory->create_apl_local takes boost::none in Pacific
- SignedTokenEngine::authenticate call to apl_factory->create_apl_local takes boost::none in Pacific
rgw_swift_auth.h:
- TempURLApplier constructor initialization of LocalApplier takes boost::none in Pacific
- SwiftAnonymousApplier constructor initialization of LocalApplier takes boost::none in Pacific
- create_apl_local uses boost::optional for perm_mask in Pacific

src/rgw/rgw_auth.cc
src/rgw/rgw_auth.h
src/rgw/rgw_auth_filters.h
src/rgw/rgw_auth_keystone.cc
src/rgw/rgw_auth_keystone.h
src/rgw/rgw_auth_s3.h
src/rgw/rgw_log.cc
src/rgw/rgw_log.h
src/rgw/rgw_rest_s3.cc
src/rgw/rgw_swift_auth.cc
src/rgw/rgw_swift_auth.h

index 42fe1133fc9878db5df20d20bf236ce9eefe4089..919be48ad7c24c28936ddd8781b7bfc39ec8b06d 100644 (file)
@@ -11,6 +11,7 @@
 #include "rgw_http_client.h"
 #include "rgw_keystone.h"
 #include "rgw_sal.h"
+#include "rgw_log.h"
 
 #include "include/str_list.h"
 
@@ -458,6 +459,9 @@ bool rgw::auth::WebIdentityApplier::is_identity(const idset_t& ids) const
     return false;
 }
 
+const std::string rgw::auth::RemoteApplier::AuthInfo::NO_SUBUSER;
+const std::string rgw::auth::RemoteApplier::AuthInfo::NO_ACCESS_KEY;
+
 /* rgw::auth::RemoteAuthApplier */
 uint32_t rgw::auth::RemoteApplier::get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const
 {
@@ -609,6 +613,12 @@ void rgw::auth::RemoteApplier::create_account(const DoutPrefixProvider* dpp,
   }
 }
 
+void rgw::auth::RemoteApplier::write_ops_log_entry(rgw_log_entry& entry) const
+{
+  entry.access_key_id = info.access_key_id;
+  entry.subuser = info.subuser;
+}
+
 /* TODO(rzarzynski): we need to handle display_name changes. */
 void rgw::auth::RemoteApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const      /* out */
 {
@@ -664,6 +674,7 @@ void rgw::auth::RemoteApplier::load_acct_info(const DoutPrefixProvider* dpp, RGW
 /* rgw::auth::LocalApplier */
 /* static declaration */
 const std::string rgw::auth::LocalApplier::NO_SUBUSER;
+const std::string rgw::auth::LocalApplier::NO_ACCESS_KEY;
 
 uint32_t rgw::auth::LocalApplier::get_perms_from_aclspec(const DoutPrefixProvider* dpp, const aclspec_t& aclspec) const
 {
@@ -742,6 +753,12 @@ void rgw::auth::LocalApplier::load_acct_info(const DoutPrefixProvider* dpp, RGWU
   user_info = this->user_info;
 }
 
+void rgw::auth::LocalApplier::write_ops_log_entry(rgw_log_entry& entry) const
+{
+  entry.access_key_id = access_key_id;
+  entry.subuser = subuser;
+}
+
 void rgw::auth::RoleApplier::to_str(std::ostream& out) const {
   out << "rgw::auth::LocalApplier(role name =" << role.name;
   for (auto& policy: role.role_policies) {
@@ -843,7 +860,7 @@ rgw::auth::AnonymousEngine::authenticate(const DoutPrefixProvider* dpp, const re
     auto apl = \
       apl_factory->create_apl_local(cct, s, user_info,
                                     rgw::auth::LocalApplier::NO_SUBUSER,
-                                    boost::none);
+                                    boost::none, rgw::auth::LocalApplier::NO_ACCESS_KEY);
     return result_t::grant(std::move(apl));
   }
 }
index c65f0b335b10565b358f6800f7fcaefa8bdc58e4..3fa02bd821fb7c7729aebd16db5169a9c8cbc87a 100644 (file)
@@ -17,6 +17,7 @@
 #define RGW_USER_ANON_ID "anonymous"
 
 class RGWCtl;
+struct rgw_log_entry;
 
 namespace rgw {
 namespace auth {
@@ -81,6 +82,9 @@ public:
   virtual string get_subuser() const = 0;
 
   virtual string get_role_tenant() const { return ""; }
+
+  /* write any auth-specific fields that are safe to expose in the ops log */
+  virtual void write_ops_log_entry(rgw_log_entry& entry) const {};
 };
 
 inline std::ostream& operator<<(std::ostream& out,
@@ -494,6 +498,8 @@ public:
     const uint32_t perm_mask;
     const bool is_admin;
     const uint32_t acct_type;
+    const std::string access_key_id;
+    const std::string subuser;
 
   public:
     enum class acct_privilege_t {
@@ -501,16 +507,23 @@ public:
       IS_PLAIN_ACCT
     };
 
+    static const std::string NO_SUBUSER;
+    static const std::string NO_ACCESS_KEY;
+
     AuthInfo(const rgw_user& acct_user,
              const std::string& acct_name,
              const uint32_t perm_mask,
              const acct_privilege_t level,
+             const std::string access_key_id,
+             const std::string subuser,
              const uint32_t acct_type=TYPE_NONE)
     : acct_user(acct_user),
       acct_name(acct_name),
       perm_mask(perm_mask),
       is_admin(acct_privilege_t::IS_ADMIN_ACCT == level),
-      acct_type(acct_type) {
+      acct_type(acct_type),
+      access_key_id(access_key_id),
+      subuser(subuser) {
     }
   };
 
@@ -560,6 +573,7 @@ public:
   uint32_t get_perm_mask() const override { return info.perm_mask; }
   void to_str(std::ostream& out) const override;
   void load_acct_info(const DoutPrefixProvider* dpp, RGWUserInfo& user_info) const override; /* out */
+  void write_ops_log_entry(rgw_log_entry& entry) const override;
   uint32_t get_identity_type() const override { return info.acct_type; }
   string get_acct_name() const override { return info.acct_name; }
   string get_subuser() const override { return {}; }
@@ -588,19 +602,23 @@ protected:
   const RGWUserInfo user_info;
   const std::string subuser;
   uint32_t perm_mask;
+  const std::string access_key_id;
 
   uint32_t get_perm_mask(const std::string& subuser_name,
                          const RGWUserInfo &uinfo) const;
 
 public:
   static const std::string NO_SUBUSER;
+  static const std::string NO_ACCESS_KEY;
 
   LocalApplier(CephContext* const cct,
                const RGWUserInfo& user_info,
                std::string subuser,
-               const boost::optional<uint32_t>& perm_mask)
+               const boost::optional<uint32_t>& perm_mask,
+               const std::string access_key_id)
     : user_info(user_info),
-      subuser(std::move(subuser)) {
+      subuser(std::move(subuser)),
+      access_key_id(access_key_id) {
     if (perm_mask) {
       this->perm_mask = perm_mask.get();
     } else {
@@ -625,6 +643,7 @@ public:
   uint32_t get_identity_type() const override { return TYPE_RGW; }
   string get_acct_name() const override { return {}; }
   string get_subuser() const override { return subuser; }
+  void write_ops_log_entry(rgw_log_entry& entry) const override;
 
   struct Factory {
     virtual ~Factory() {}
@@ -632,7 +651,8 @@ public:
                                       const req_state* s,
                                       const RGWUserInfo& user_info,
                                       const std::string& subuser,
-                                      const boost::optional<uint32_t>& perm_mask) const = 0;
+                                      const boost::optional<uint32_t>& perm_mask,
+                                      const std::string& access_key_id) const = 0;
     };
 };
 
index bea9665e4167d910868cf7859fd592780e69712e..1b59f3bb25a1bed099bc862a664add518429b11b 100644 (file)
@@ -118,6 +118,10 @@ public:
   void modify_request_state(const DoutPrefixProvider* dpp, req_state * s) const override {     /* in/out */
     return get_decoratee().modify_request_state(dpp, s);
   }
+
+  void write_ops_log_entry(rgw_log_entry& entry) const override {
+    return get_decoratee().write_ops_log_entry(entry);
+  }
 };
 
 
index 124b50793e4da3b7e63d1f9a8487c0155b5cbe67..0d45af085b5cb3146cb7d335cb62cbe64beaff5f 100644 (file)
@@ -133,8 +133,10 @@ TokenEngine::get_creds_info(const TokenEngine::token_envelope_t& token,
      * the access rights through the perm_mask. At least at this layer. */
     RGW_PERM_FULL_CONTROL,
     level,
-    TYPE_KEYSTONE,
-  };
+    rgw::auth::RemoteApplier::AuthInfo::NO_ACCESS_KEY,
+    rgw::auth::RemoteApplier::AuthInfo::NO_SUBUSER,
+    TYPE_KEYSTONE
+};
 }
 
 static inline const std::string
@@ -497,7 +499,8 @@ EC2Engine::get_acl_strategy(const EC2Engine::token_envelope_t&) const
 
 EC2Engine::auth_info_t
 EC2Engine::get_creds_info(const EC2Engine::token_envelope_t& token,
-                          const std::vector<std::string>& admin_roles
+                          const std::vector<std::string>& admin_roles,
+                          const std::string& access_key_id
                          ) const noexcept
 {
   using acct_privilege_t = \
@@ -521,7 +524,9 @@ EC2Engine::get_creds_info(const EC2Engine::token_envelope_t& token,
      * the access rights through the perm_mask. At least at this layer. */
     RGW_PERM_FULL_CONTROL,
     level,
-    TYPE_KEYSTONE,
+    access_key_id,
+    rgw::auth::RemoteApplier::AuthInfo::NO_SUBUSER,
+    TYPE_KEYSTONE
   };
 }
 
@@ -589,7 +594,7 @@ rgw::auth::Engine::result_t EC2Engine::authenticate(
                   << " expires: " << t->get_expires() << dendl;
 
     auto apl = apl_factory->create_apl_remote(cct, s, get_acl_strategy(*t),
-                                              get_creds_info(*t, accepted_roles.admin));
+                                              get_creds_info(*t, accepted_roles.admin, std::string(access_key_id)));
     return result_t::grant(std::move(apl), completer_factory(boost::none));
   }
 }
index 4ad20442b96beb729e25c199461ef9821d2d2a55..c9addb0098ace69e116fb12667fbf72c2264b593 100644 (file)
@@ -138,7 +138,8 @@ class EC2Engine : public rgw::auth::s3::AWSEngine {
   /* Helper methods. */
   acl_strategy_t get_acl_strategy(const token_envelope_t& token) const;
   auth_info_t get_creds_info(const token_envelope_t& token,
-                             const std::vector<std::string>& admin_roles
+                             const std::vector<std::string>& admin_roles,
+                             const std::string& access_key_id
                             ) const noexcept;
   std::pair<boost::optional<token_envelope_t>, int>
   get_from_keystone(const DoutPrefixProvider* dpp,
index 4288bd2f0d4e040789f0fe28a660ce2e62b7e611..cc1dbf90b0e5e4719ff7fd342db541722bae2812 100644 (file)
@@ -56,9 +56,10 @@ class STSAuthStrategy : public rgw::auth::Strategy,
                             const req_state* const s,
                             const RGWUserInfo& user_info,
                             const std::string& subuser,
-                            const boost::optional<uint32_t>& perm_mask) const override {
+                            const boost::optional<uint32_t>& perm_mask,
+                            const std::string& access_key_id) const override {
     auto apl = rgw::auth::add_sysreq(cct, ctl, s,
-      rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask));
+      rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask, access_key_id));
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
 
@@ -178,9 +179,10 @@ class AWSAuthStrategy : public rgw::auth::Strategy,
                             const req_state* const s,
                             const RGWUserInfo& user_info,
                             const std::string& subuser,
-                            const boost::optional<uint32_t>& perm_mask) const override {
+                            const boost::optional<uint32_t>& perm_mask,
+                            const std::string& access_key_id) const override {
     auto apl = rgw::auth::add_sysreq(cct, ctl, s,
-      rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask));
+      rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask, access_key_id));
     /* TODO(rzarzynski): replace with static_ptr. */
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }
index 5876b1789bff22efa4c769810e7afc4bccd5521c..f53b82b9044ba31903ef61fbcc4edc92afe08b3a 100644 (file)
@@ -313,7 +313,13 @@ void rgw_format_ops_log_entry(struct rgw_log_entry& entry, Formatter *formatter)
       formatter->close_section();
     }
   }
-
+  if (!entry.access_key_id.empty()) {
+    formatter->dump_string("access_key_id", entry.access_key_id);
+  }
+  if (!entry.subuser.empty()) {
+    formatter->dump_string("subuser", entry.subuser);
+  }
+  formatter->dump_bool("temp_url", entry.temp_url);
   formatter->close_section();
 }
 
@@ -587,6 +593,7 @@ int rgw_log_op(RGWREST* const rest, struct req_state *s, const string& op_name,
 
   if (s->auth.identity) {
     entry.identity_type = s->auth.identity->get_identity_type();
+    s->auth.identity->write_ops_log_entry(entry);
   } else {
     entry.identity_type = TYPE_NONE;
   }
index 5f5951f9e2434088dcbd010fcd16fa9f8f16bf10..d53a9bc4dff0ab59d71b0ee98e91161e54fd18a8 100644 (file)
@@ -41,9 +41,12 @@ struct rgw_log_entry {
   string trans_id;
   std::vector<string> token_claims;
   uint32_t identity_type;
+  std::string access_key_id;
+  std::string subuser;
+  bool temp_url {false};
 
   void encode(bufferlist &bl) const {
-    ENCODE_START(12, 5, bl);
+    ENCODE_START(13, 5, bl);
     encode(object_owner.id, bl);
     encode(bucket_owner.id, bl);
     encode(bucket, bl);
@@ -69,10 +72,13 @@ struct rgw_log_entry {
     encode(trans_id, bl);
     encode(token_claims, bl);
     encode(identity_type,bl);
+    encode(access_key_id, bl);
+    encode(subuser, bl);
+    encode(temp_url, bl);
     ENCODE_FINISH(bl);
   }
   void decode(bufferlist::const_iterator &p) {
-    DECODE_START_LEGACY_COMPAT_LEN(12, 5, 5, p);
+    DECODE_START_LEGACY_COMPAT_LEN(13, 5, 5, p);
     decode(object_owner.id, p);
     if (struct_v > 3)
       decode(bucket_owner.id, p);
@@ -127,6 +133,11 @@ struct rgw_log_entry {
     if (struct_v >= 12) {
       decode(identity_type, p);
     }
+    if (struct_v >= 13) {
+      decode(access_key_id, p);
+      decode(subuser, p);
+      decode(temp_url, p);
+    }
     DECODE_FINISH(p);
   }
   void dump(ceph::Formatter *f) const;
index 724c3d30d84b79842583fe47c273013757b52afc..a2ea5f8dc27eac33237248761b5e6496e2801dc4 100644 (file)
@@ -5667,6 +5667,8 @@ rgw::auth::s3::LDAPEngine::get_creds_info(const rgw::RGWToken& token) const noex
     token.id,
     RGW_PERM_FULL_CONTROL,
     acct_privilege_t::IS_PLAIN_ACCT,
+    rgw::auth::RemoteApplier::AuthInfo::NO_ACCESS_KEY,
+    rgw::auth::RemoteApplier::AuthInfo::NO_SUBUSER,
     TYPE_LDAP
   };
 }
@@ -5776,7 +5778,7 @@ rgw::auth::s3::LocalEngine::authenticate(
     return result_t::deny(-ERR_SIGNATURE_NO_MATCH);
   }
 
-  auto apl = apl_factory->create_apl_local(cct, s, user_info, k.subuser, boost::none);
+  auto apl = apl_factory->create_apl_local(cct, s, user_info, k.subuser, boost::none, access_key_id);
   return result_t::grant(std::move(apl), completer_factory(k.key));
 }
 
@@ -5791,6 +5793,8 @@ rgw::auth::s3::STSEngine::get_creds_info(const STS::SessionToken& token) const n
     token.acct_name,
     token.perm_mask,
     (token.is_admin) ? acct_privilege_t::IS_ADMIN_ACCT: acct_privilege_t::IS_PLAIN_ACCT,
+    token.access_key_id,
+    rgw::auth::RemoteApplier::AuthInfo::NO_SUBUSER,
     token.acct_type
   };
 }
@@ -5950,7 +5954,7 @@ rgw::auth::s3::STSEngine::authenticate(
     return result_t::grant(std::move(apl), completer_factory(token.secret_access_key));
   } else { // This is for all local users of type TYPE_RGW or TYPE_NONE
     string subuser;
-    auto apl = local_apl_factory->create_apl_local(cct, s, user_info, subuser, token.perm_mask);
+    auto apl = local_apl_factory->create_apl_local(cct, s, user_info, subuser, token.perm_mask, std::string(_access_key_id));
     return result_t::grant(std::move(apl), completer_factory(token.secret_access_key));
   }
 }
index da0a370b71ab7b6f231ff4654e49710c4be80889..4c85d82baebcb00f4f9c1cec2e10a0851d3c8246 100644 (file)
@@ -60,6 +60,12 @@ void TempURLApplier::modify_request_state(const DoutPrefixProvider* dpp, req_sta
 
 }
 
+void TempURLApplier::write_ops_log_entry(rgw_log_entry& entry) const
+{
+  LocalApplier::write_ops_log_entry(entry);
+  entry.temp_url = true;
+}
+
 /* TempURL: engine */
 bool TempURLEngine::is_applicable(const req_state* const s) const noexcept
 {
@@ -457,7 +463,8 @@ ExternalTokenEngine::authenticate(const DoutPrefixProvider* dpp,
 
   auto apl = apl_factory->create_apl_local(cct, s, tmp_uinfo,
                                            extract_swift_subuser(swift_user),
-                                           boost::none);
+                                           boost::none,
+                                           rgw::auth::LocalApplier::NO_ACCESS_KEY);
   return result_t::grant(std::move(apl));
 }
 
@@ -611,7 +618,7 @@ SignedTokenEngine::authenticate(const DoutPrefixProvider* dpp,
 
   auto apl = apl_factory->create_apl_local(cct, s, user_info,
                                            extract_swift_subuser(swift_user),
-                                           boost::none);
+                                           boost::none, rgw::auth::LocalApplier::NO_ACCESS_KEY);
   return result_t::grant(std::move(apl));
 }
 
index ba319405bfd47f385b46934308db1934d74dd455..2aa89caf599c4c2ec0eaa53d43def557efc74062 100644 (file)
@@ -24,10 +24,11 @@ class TempURLApplier : public rgw::auth::LocalApplier {
 public:
   TempURLApplier(CephContext* const cct,
                  const RGWUserInfo& user_info)
-    : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, boost::none) {
+    : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, boost::none, 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;
 
   struct Factory {
     virtual ~Factory() {}
@@ -153,7 +154,7 @@ class SwiftAnonymousApplier : public rgw::auth::LocalApplier {
   public:
     SwiftAnonymousApplier(CephContext* const cct,
                           const RGWUserInfo& user_info)
-      : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, boost::none) {
+      : LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, boost::none, LocalApplier::NO_ACCESS_KEY) {
       };
     bool is_admin_of(const rgw_user& uid) const {return false;}
     bool is_owner_of(const rgw_user& uid) const {return uid.id.compare(RGW_USER_ANON_ID) == 0;}
@@ -225,11 +226,12 @@ class DefaultStrategy : public rgw::auth::Strategy,
                             const req_state* const s,
                             const RGWUserInfo& user_info,
                             const std::string& subuser,
-                            const boost::optional<uint32_t>& perm_mask) const override {
+                            const boost::optional<uint32_t>& perm_mask,
+                            const std::string& access_key_id) const override {
     auto apl = \
       rgw::auth::add_3rdparty(ctl, rgw_user(s->account_name),
         rgw::auth::add_sysreq(cct, ctl, s,
-          rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask)));
+          rgw::auth::LocalApplier(cct, user_info, subuser, perm_mask, access_key_id)));
     /* TODO(rzarzynski): replace with static_ptr. */
     return aplptr_t(new decltype(apl)(std::move(apl)));
   }