mirror of
https://github.com/ceph/ceph
synced 2025-02-24 11:37:37 +00:00
rgw: log identity applier metadata in ops logs
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>
This commit is contained in:
parent
52f341b00a
commit
ebf4209fa7
@ -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"
|
||||
|
||||
@ -513,6 +514,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
|
||||
{
|
||||
@ -662,6 +666,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 */
|
||||
{
|
||||
@ -723,6 +733,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
|
||||
{
|
||||
@ -801,6 +812,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::RoleApplier(role name =" << role.name;
|
||||
for (auto& policy: role.role_policies) {
|
||||
@ -911,7 +928,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,
|
||||
std::nullopt);
|
||||
std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
|
||||
return result_t::grant(std::move(apl));
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define RGW_USER_ANON_ID "anonymous"
|
||||
|
||||
class RGWCtl;
|
||||
struct rgw_log_entry;
|
||||
|
||||
namespace rgw {
|
||||
namespace auth {
|
||||
@ -82,6 +83,9 @@ public:
|
||||
virtual std::string get_subuser() const = 0;
|
||||
|
||||
virtual std::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,
|
||||
@ -542,6 +546,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 {
|
||||
@ -549,16 +555,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) {
|
||||
}
|
||||
};
|
||||
|
||||
@ -608,6 +621,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; }
|
||||
std::string get_acct_name() const override { return info.acct_name; }
|
||||
std::string get_subuser() const override { return {}; }
|
||||
@ -636,20 +650,24 @@ 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 std::optional<uint32_t>& perm_mask)
|
||||
const std::optional<uint32_t>& perm_mask,
|
||||
const std::string access_key_id)
|
||||
: user_info(user_info),
|
||||
subuser(std::move(subuser)),
|
||||
perm_mask(perm_mask.value_or(RGW_PERM_INVALID)) {
|
||||
perm_mask(perm_mask.value_or(RGW_PERM_INVALID)),
|
||||
access_key_id(access_key_id) {
|
||||
}
|
||||
|
||||
|
||||
@ -669,6 +687,7 @@ public:
|
||||
uint32_t get_identity_type() const override { return TYPE_RGW; }
|
||||
std::string get_acct_name() const override { return {}; }
|
||||
std::string get_subuser() const override { return subuser; }
|
||||
void write_ops_log_entry(rgw_log_entry& entry) const override;
|
||||
|
||||
struct Factory {
|
||||
virtual ~Factory() {}
|
||||
@ -676,7 +695,8 @@ public:
|
||||
const req_state* s,
|
||||
const RGWUserInfo& user_info,
|
||||
const std::string& subuser,
|
||||
const std::optional<uint32_t>& perm_mask) const = 0;
|
||||
const std::optional<uint32_t>& perm_mask,
|
||||
const std::string& access_key_id) const = 0;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -134,8 +134,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
|
||||
@ -498,7 +500,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 = \
|
||||
@ -522,7 +525,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
|
||||
};
|
||||
}
|
||||
|
||||
@ -590,7 +595,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));
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -43,8 +43,7 @@ class STSAuthStrategy : public rgw::auth::Strategy,
|
||||
aplptr_t create_apl_remote(CephContext* const cct,
|
||||
const req_state* const s,
|
||||
rgw::auth::RemoteApplier::acl_strategy_t&& acl_alg,
|
||||
const rgw::auth::RemoteApplier::AuthInfo &info
|
||||
) const override {
|
||||
const rgw::auth::RemoteApplier::AuthInfo &info) const override {
|
||||
auto apl = rgw::auth::add_sysreq(cct, store, s,
|
||||
rgw::auth::RemoteApplier(cct, store, std::move(acl_alg), info,
|
||||
implicit_tenant_context,
|
||||
@ -56,9 +55,10 @@ class STSAuthStrategy : public rgw::auth::Strategy,
|
||||
const req_state* const s,
|
||||
const RGWUserInfo& user_info,
|
||||
const std::string& subuser,
|
||||
const std::optional<uint32_t>& perm_mask) const override {
|
||||
const std::optional<uint32_t>& perm_mask,
|
||||
const std::string& access_key_id) const override {
|
||||
auto apl = rgw::auth::add_sysreq(cct, store, 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)));
|
||||
}
|
||||
|
||||
@ -109,8 +109,7 @@ class ExternalAuthStrategy : public rgw::auth::Strategy,
|
||||
aplptr_t create_apl_remote(CephContext* const cct,
|
||||
const req_state* const s,
|
||||
rgw::auth::RemoteApplier::acl_strategy_t&& acl_alg,
|
||||
const rgw::auth::RemoteApplier::AuthInfo &info
|
||||
) const override {
|
||||
const rgw::auth::RemoteApplier::AuthInfo &info) const override {
|
||||
auto apl = rgw::auth::add_sysreq(cct, store, s,
|
||||
rgw::auth::RemoteApplier(cct, store, std::move(acl_alg), info,
|
||||
implicit_tenant_context,
|
||||
@ -174,9 +173,10 @@ class AWSAuthStrategy : public rgw::auth::Strategy,
|
||||
const req_state* const s,
|
||||
const RGWUserInfo& user_info,
|
||||
const std::string& subuser,
|
||||
const std::optional<uint32_t>& perm_mask) const override {
|
||||
const std::optional<uint32_t>& perm_mask,
|
||||
const std::string& access_key_id) const override {
|
||||
auto apl = rgw::auth::add_sysreq(cct, store, 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)));
|
||||
}
|
||||
|
@ -316,7 +316,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();
|
||||
}
|
||||
|
||||
@ -595,6 +601,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;
|
||||
}
|
||||
|
@ -41,9 +41,12 @@ struct rgw_log_entry {
|
||||
std::string trans_id;
|
||||
std::vector<std::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;
|
||||
|
@ -5963,6 +5963,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
|
||||
};
|
||||
}
|
||||
@ -6073,7 +6075,7 @@ rgw::auth::s3::LocalEngine::authenticate(
|
||||
}
|
||||
|
||||
auto apl = apl_factory->create_apl_local(cct, s, user->get_info(),
|
||||
k.subuser, std::nullopt);
|
||||
k.subuser, std::nullopt, access_key_id);
|
||||
return result_t::grant(std::move(apl), completer_factory(k.key));
|
||||
}
|
||||
|
||||
@ -6088,6 +6090,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
|
||||
};
|
||||
}
|
||||
@ -6253,7 +6257,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->get_info(), subuser, token.perm_mask);
|
||||
auto apl = local_apl_factory->create_apl_local(cct, s, user->get_info(), subuser, token.perm_mask, std::string(_access_key_id));
|
||||
return result_t::grant(std::move(apl), completer_factory(token.secret_access_key));
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,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
|
||||
{
|
||||
@ -461,7 +467,7 @@ ExternalTokenEngine::authenticate(const DoutPrefixProvider* dpp,
|
||||
|
||||
auto apl = apl_factory->create_apl_local(cct, s, user->get_info(),
|
||||
extract_swift_subuser(swift_user),
|
||||
std::nullopt);
|
||||
std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
|
||||
return result_t::grant(std::move(apl));
|
||||
}
|
||||
|
||||
@ -615,7 +621,7 @@ SignedTokenEngine::authenticate(const DoutPrefixProvider* dpp,
|
||||
|
||||
auto apl = apl_factory->create_apl_local(cct, s, user->get_info(),
|
||||
extract_swift_subuser(swift_user),
|
||||
std::nullopt);
|
||||
std::nullopt, rgw::auth::LocalApplier::NO_ACCESS_KEY);
|
||||
return result_t::grant(std::move(apl));
|
||||
}
|
||||
|
||||
|
@ -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, std::nullopt) {
|
||||
: LocalApplier(cct, user_info, 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;
|
||||
|
||||
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, std::nullopt) {
|
||||
: LocalApplier(cct, user_info, LocalApplier::NO_SUBUSER, std::nullopt, 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 std::optional<uint32_t>& perm_mask) const override {
|
||||
const std::optional<uint32_t>& perm_mask,
|
||||
const std::string& access_key_id) const override {
|
||||
auto apl = \
|
||||
rgw::auth::add_3rdparty(store, rgw_user(s->account_name),
|
||||
rgw::auth::add_sysreq(cct, store, 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)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user