From: Casey Bodley Date: Sun, 17 Dec 2023 20:03:53 +0000 (-0500) Subject: rgw/iam: add iam user metadata (path, create_date, tags) X-Git-Tag: v19.1.0~99^2~127 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=cfc53106883294ef3f8707127d65e0a9e87cfc09;p=ceph.git rgw/iam: add iam user metadata (path, create_date, tags) Signed-off-by: Casey Bodley (cherry picked from commit de9feeb32ca71c67b29e753c3164cd778c08c280) --- diff --git a/src/rgw/driver/rados/rgw_rest_user.cc b/src/rgw/driver/rados/rgw_rest_user.cc index 9f3ae2d03aa76..34112c9472792 100644 --- a/src/rgw/driver/rados/rgw_rest_user.cc +++ b/src/rgw/driver/rados/rgw_rest_user.cc @@ -22,6 +22,7 @@ using namespace std; int fetch_access_keys_from_master(const DoutPrefixProvider* dpp, req_state* s, std::map& keys, + ceph::real_time& create_date, optional_yield y) { bufferlist data; @@ -36,6 +37,7 @@ int fetch_access_keys_from_master(const DoutPrefixProvider* dpp, req_state* s, RGWUserInfo ui; ui.decode_json(&jp); keys = std::move(ui.access_keys); + create_date = ui.create_date; return 0; } @@ -188,6 +190,7 @@ void RGWOp_User_Create::execute(optional_yield y) RESTArgs::get_string(s, "default-placement", default_placement_str, &default_placement_str); RESTArgs::get_string(s, "placement-tags", placement_tags_str, &placement_tags_str); RESTArgs::get_string(s, "account-id", "", &op_state.account_id); + RESTArgs::get_string(s, "path", "", &op_state.path); if (!s->user->get_info().system && system) { ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl; @@ -264,7 +267,9 @@ void RGWOp_User_Create::execute(optional_yield y) } if (!s->penv.site->is_meta_master()) { - op_ret = fetch_access_keys_from_master(this, s, op_state.op_access_keys, y); + op_state.create_date.emplace(); + op_ret = fetch_access_keys_from_master(this, s, op_state.op_access_keys, + *op_state.create_date, y); if (op_ret < 0) { return; } @@ -333,6 +338,7 @@ void RGWOp_User_Modify::execute(optional_yield y) RESTArgs::get_string(s, "default-placement", default_placement_str, &default_placement_str); RESTArgs::get_string(s, "placement-tags", placement_tags_str, &placement_tags_str); RESTArgs::get_string(s, "account-id", "", &op_state.account_id); + RESTArgs::get_string(s, "path", "", &op_state.path); if (!s->user->get_info().system && system) { ldpp_dout(this, 0) << "cannot set system flag by non-system user" << dendl; @@ -414,7 +420,9 @@ void RGWOp_User_Modify::execute(optional_yield y) } if (!s->penv.site->is_meta_master()) { - op_ret = fetch_access_keys_from_master(this, s, op_state.op_access_keys, y); + op_state.create_date.emplace(); + op_ret = fetch_access_keys_from_master(this, s, op_state.op_access_keys, + *op_state.create_date, y); if (op_ret < 0) { return; } diff --git a/src/rgw/driver/rados/rgw_user.cc b/src/rgw/driver/rados/rgw_user.cc index e27cd81fb9d0b..348d876bfe2a4 100644 --- a/src/rgw/driver/rados/rgw_user.cc +++ b/src/rgw/driver/rados/rgw_user.cc @@ -1784,6 +1784,18 @@ int RGWUser::execute_add(const DoutPrefixProvider *dpp, RGWUserAdminOpState& op_ user_info.type = TYPE_ROOT; } + if (!op_state.path.empty()) { + user_info.path = op_state.path; + } else { + user_info.path = "/"; + } + + if (op_state.create_date) { + user_info.create_date = *op_state.create_date; + } else { + user_info.create_date = ceph::real_clock::now(); + } + // update the request op_state.set_user_info(user_info); op_state.set_populated(); @@ -2106,6 +2118,14 @@ int RGWUser::execute_modify(const DoutPrefixProvider *dpp, RGWUserAdminOpState& user_info.type = op_state.account_root ? TYPE_ROOT : TYPE_RGW; } + if (!op_state.path.empty()) { + user_info.path = op_state.path; + } + + if (op_state.create_date) { + user_info.create_date = *op_state.create_date; + } + op_state.set_user_info(user_info); // if we're supposed to modify keys, do so diff --git a/src/rgw/driver/rados/rgw_user.h b/src/rgw/driver/rados/rgw_user.h index 463857899db5f..c8c3c6dade5a2 100644 --- a/src/rgw/driver/rados/rgw_user.h +++ b/src/rgw/driver/rados/rgw_user.h @@ -124,6 +124,8 @@ struct RGWUserAdminOpState { uint32_t op_mask{0}; std::map temp_url_keys; std::string account_id; + std::string path; + std::optional create_date; // subuser attributes std::string subuser; diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index 76d360c33d7f0..0fcc79bed9804 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -6550,6 +6550,7 @@ int main(int argc, const char **argv) if (!tags.empty()) { user_op.set_placement_tags(tags); } + user_op.path = path; user_op.account_id = account_id; bucket_op.account_id = account_id; diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index 5de470d9281f9..752bdb1bb96d4 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -2592,6 +2592,10 @@ void RGWUserInfo::generate_test_instances(list& o) i->user_id = "user_id"; i->display_name = "display_name"; i->user_email = "user@email"; + i->account_id = "RGW12345678901234567"; + i->path = "/"; + i->create_date = ceph::real_time{std::chrono::hours(1)}; + i->tags.emplace("key", "value"); RGWAccessKey k1, k2; k1.id = "id1"; k1.key = "key1"; @@ -2825,6 +2829,9 @@ void RGWUserInfo::dump(Formatter *f) const encode_json("type", user_source_type, f); encode_json("mfa_ids", mfa_ids, f); encode_json("account_id", account_id, f); + encode_json("path", path, f); + encode_json("create_date", create_date, f); + encode_json("tags", tags, f); } void RGWUserInfo::decode_json(JSONObj *obj) @@ -2879,6 +2886,9 @@ void RGWUserInfo::decode_json(JSONObj *obj) } JSONDecoder::decode_json("mfa_ids", mfa_ids, obj); JSONDecoder::decode_json("account_id", account_id, obj); + JSONDecoder::decode_json("path", path, obj); + JSONDecoder::decode_json("create_date", create_date, obj); + JSONDecoder::decode_json("tags", tags, obj); } diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index 61005bf4f2bff..35d097ef1c0d9 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -583,6 +583,9 @@ struct RGWUserInfo uint32_t type; std::set mfa_ids; rgw_account_id account_id; + std::string path = "/"; + ceph::real_time create_date; + std::multimap tags; RGWUserInfo() : suspended(0), @@ -651,6 +654,9 @@ struct RGWUserInfo } encode(user_id.ns, bl); encode(account_id, bl); + encode(path, bl); + encode(create_date, bl); + encode(tags, bl); ENCODE_FINISH(bl); } void decode(bufferlist::const_iterator& bl) { @@ -743,6 +749,11 @@ struct RGWUserInfo } if (struct_v >= 23) { decode(account_id, bl); + decode(path, bl); + decode(create_date, bl); + decode(tags, bl); + } else { + path = "/"; } DECODE_FINISH(bl); } diff --git a/src/rgw/rgw_xml.cc b/src/rgw/rgw_xml.cc index 1bcbcdad2457b..3ce031c2faaaf 100644 --- a/src/rgw/rgw_xml.cc +++ b/src/rgw/rgw_xml.cc @@ -431,6 +431,20 @@ void decode_xml_obj(utime_t& val, XMLObj *obj) } } +void decode_xml_obj(ceph::real_time& val, XMLObj *obj) +{ + const std::string s = obj->get_data(); + uint64_t epoch; + uint64_t nsec; + int r = utime_t::parse_date(s, &epoch, &nsec); + if (r == 0) { + using namespace std::chrono; + val = real_time{seconds(epoch) + nanoseconds(nsec)}; + } else { + throw RGWXMLDecoder::err("failed to decode real_time"); + } +} + void encode_xml(const char *name, const string& val, Formatter *f) { f->dump_string(name, val); diff --git a/src/rgw/rgw_xml.h b/src/rgw/rgw_xml.h index 5d3e727895232..8e2a281b64980 100644 --- a/src/rgw/rgw_xml.h +++ b/src/rgw/rgw_xml.h @@ -9,6 +9,7 @@ #include #include #include +#include "common/ceph_time.h" class XMLObj; class RGWXMLParser; @@ -190,6 +191,7 @@ void decode_xml_obj(bool& val, XMLObj *obj); void decode_xml_obj(bufferlist& val, XMLObj *obj); class utime_t; void decode_xml_obj(utime_t& val, XMLObj *obj); +void decode_xml_obj(ceph::real_time& val, XMLObj *obj); template void decode_xml_obj(std::optional& val, XMLObj *obj)