From 956997cff945430b046b2daa1344208d652a4b3b Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Sun, 3 Dec 2017 23:51:38 -0800 Subject: [PATCH] rgw: add otp pool, create otp service functionality Signed-off-by: Yehuda Sadeh --- src/rgw/rgw_json_enc.cc | 2 ++ src/rgw/rgw_rados.cc | 73 +++++++++++++++++++++++++++++++++++++---- src/rgw/rgw_rados.h | 14 ++++++++ 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/rgw/rgw_json_enc.cc b/src/rgw/rgw_json_enc.cc index af0bf3ba936..e11ab1ae126 100644 --- a/src/rgw/rgw_json_enc.cc +++ b/src/rgw/rgw_json_enc.cc @@ -919,6 +919,7 @@ void RGWZoneParams::dump(Formatter *f) const encode_json("user_email_pool", user_email_pool, f); encode_json("user_swift_pool", user_swift_pool, f); encode_json("user_uid_pool", user_uid_pool, f); + encode_json("otp_pool", otp_pool, f); encode_json_plain("system_key", system_key, f); encode_json("placement_pools", placement_pools, f); encode_json("metadata_heap", metadata_heap, f); @@ -961,6 +962,7 @@ void RGWZoneParams::decode_json(JSONObj *obj) JSONDecoder::decode_json("user_email_pool", user_email_pool, obj); JSONDecoder::decode_json("user_swift_pool", user_swift_pool, obj); JSONDecoder::decode_json("user_uid_pool", user_uid_pool, obj); + JSONDecoder::decode_json("otp_pool", otp_pool, obj); JSONDecoder::decode_json("system_key", system_key, obj); JSONDecoder::decode_json("placement_pools", placement_pools, obj); JSONDecoder::decode_json("metadata_heap", metadata_heap, obj); diff --git a/src/rgw/rgw_rados.cc b/src/rgw/rgw_rados.cc index b0f9d858c69..106167ba488 100644 --- a/src/rgw/rgw_rados.cc +++ b/src/rgw/rgw_rados.cc @@ -40,6 +40,7 @@ #include "cls/timeindex/cls_timeindex_client.h" #include "cls/lock/cls_lock_client.h" #include "cls/user/cls_user_client.h" +#include "cls/otp/cls_otp_client.h" #include "osd/osd_types.h" #include "rgw_tools.h" @@ -1696,6 +1697,7 @@ int get_zones_pool_set(CephContext* cct, pool_names.insert(zone.user_email_pool); pool_names.insert(zone.user_swift_pool); pool_names.insert(zone.user_uid_pool); + pool_names.insert(zone.otp_pool); pool_names.insert(zone.roles_pool); pool_names.insert(zone.reshard_pool); for(auto& iter : zone.placement_pools) { @@ -1769,6 +1771,7 @@ int RGWZoneParams::fix_pool_names() user_uid_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:users.uid", user_uid_pool); roles_pool = fix_zone_pool_dup(pools, name, ".rgw.meta:roles", roles_pool); reshard_pool = fix_zone_pool_dup(pools, name, ".rgw.log:reshard", reshard_pool); + otp_pool = fix_zone_pool_dup(pools, name, ".rgw.otp", otp_pool); for(auto& iter : placement_pools) { iter.second.index_pool = fix_zone_pool_dup(pools, name, "." + default_bucket_index_pool_suffix, @@ -14158,21 +14161,64 @@ void RGWRados::call_zap() { return; } -int RGWRados::check_mfa(const rgw_user& user, const string& otp_id, const string& pin) +int RGWRados::get_mfa_ref(const rgw_user& user, rgw_rados_ref *ref) { string oid = string("user:") + user.to_str(); rgw_raw_obj obj(get_zone_params().otp_pool, oid); + return get_system_obj_ref(obj, ref); +} +int RGWRados::check_mfa(const rgw_user& user, const string& otp_id, const string& pin) +{ rgw_rados_ref ref; - int r = get_system_obj_ref(obj, &ref); + + int r = get_mfa_ref(user, &ref); if (r < 0) { return r; } - otp_check_t result; + rados::cls::otp::otp_check_t result; + + r = rados::cls::otp::OTP::check(cct, ref.ioctx, ref.oid, otp_id, pin, &result); + if (r < 0) + return r; + + ldout(cct, 20) << "OTP check, otp_id=" << otp_id << " result=" << (int)result.result << dendl; + + return (result.result == rados::cls::otp::OTP_CHECK_SUCCESS ? 0 : -EACCES); +} + +int RGWRados::create_mfa(const rgw_user& user, const rados::cls::otp::otp_info_t& config) +{ + rgw_rados_ref ref; + + int r = get_mfa_ref(user, &ref); + if (r < 0) { + return r; + } librados::ObjectWriteOperation op; - rados::cls::otp::OTP::check(ref.io_ctx, obj.get_oid(), otp_id, pin, &result); + rados::cls::otp::OTP::create(&op, config); + r = ref.ioctx.operate(ref.oid, &op); + if (r < 0) { + ldout(cct, 20) << "OTP create, otp_id=" << config.id << " result=" << (int)r << dendl; + return r; + } + + return 0; +} + +int RGWRados::remove_mfa(const rgw_user& user, const string& id) +{ + rgw_rados_ref ref; + + int r = get_mfa_ref(user, &ref); + if (r < 0) { + return r; + } + + librados::ObjectWriteOperation op; + rados::cls::otp::OTP::remove(&op, id); r = ref.ioctx.operate(ref.oid, &op); if (r < 0) { ldout(cct, 20) << "OTP remove, otp_id=" << id << " result=" << (int)r << dendl; @@ -14196,8 +14242,23 @@ int RGWRados::get_mfa(const rgw_user& user, const string& id, rados::cls::otp::o return r; } - ldout(cct, 20) << "OTP check, otp_id=" << otp_id << " result=" << (int)result << dendl; + return 0; +} + +int RGWRados::list_mfa(const rgw_user& user, list *result) +{ + rgw_rados_ref ref; + + int r = get_mfa_ref(user, &ref); + if (r < 0) { + return r; + } + + r = rados::cls::otp::OTP::get_all(ref.ioctx, ref.oid, result); + if (r < 0) { + return r; + } - return (result.result == rados::cls::otp::OTP_CHECK ? 0 : -EACCES); + return 0; } diff --git a/src/rgw/rgw_rados.h b/src/rgw/rgw_rados.h index ddcd3ef62d2..48217675089 100644 --- a/src/rgw/rgw_rados.h +++ b/src/rgw/rgw_rados.h @@ -19,6 +19,7 @@ #include "cls/log/cls_log_types.h" #include "cls/statelog/cls_statelog_types.h" #include "cls/timeindex/cls_timeindex_types.h" +#include "cls/otp/cls_otp_types.h" #include "rgw_log.h" #include "rgw_metadata.h" #include "rgw_meta_sync_status.h" @@ -1188,6 +1189,7 @@ struct RGWZoneParams : RGWSystemMetaObj { rgw_pool user_uid_pool; rgw_pool roles_pool; rgw_pool reshard_pool; + rgw_pool otp_pool; RGWAccessKey system_key; @@ -1241,6 +1243,7 @@ struct RGWZoneParams : RGWSystemMetaObj { encode(tier_config, bl); encode(roles_pool, bl); encode(reshard_pool, bl); + encode(otp_pool, bl); ENCODE_FINISH(bl); } @@ -1289,6 +1292,11 @@ struct RGWZoneParams : RGWSystemMetaObj { } else { reshard_pool = log_pool.name + ":reshard"; } + if (struct_v >= 11) { + ::decode(otp_pool, bl); + } else { + otp_pool = name + ".rgw.otp"; + } DECODE_FINISH(bl); } void dump(Formatter *f) const; @@ -3707,7 +3715,13 @@ public: int delete_obj_aio(const rgw_obj& obj, RGWBucketInfo& info, RGWObjState *astate, list& handles, bool keep_index_consistent); + /* mfa/totp stuff */ + int get_mfa_ref(const rgw_user& user, rgw_rados_ref *ref); int check_mfa(const rgw_user& user, const string& otp_id, const string& pin); + int create_mfa(const rgw_user& user, const rados::cls::otp::otp_info_t& config); + int remove_mfa(const rgw_user& user, const string& id); + int get_mfa(const rgw_user& user, const string& id, rados::cls::otp::otp_info_t *result); + int list_mfa(const rgw_user& user, list *result); private: /** * This is a helper method, it generates a list of bucket index objects with the given -- 2.39.5