From 3ab463f9f538a08fd11db2b654004449994dd0fe Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Sun, 3 Dec 2017 23:54:33 -0800 Subject: [PATCH] rgw-admin: new mfa control commands Signed-off-by: Yehuda Sadeh --- src/rgw/CMakeLists.txt | 11 +-- src/rgw/rgw_admin.cc | 178 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+), 5 deletions(-) diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index e28fa309f450f..e29c89f935c3d 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -149,7 +149,7 @@ if(WITH_LTTNG) add_dependencies(rgw_a rgw_op-tp rgw_rados-tp) endif() -target_link_libraries(rgw_a librados cls_lock_client cls_rgw_client cls_refcount_client +target_link_libraries(rgw_a librados cls_otp_client cls_lock_client cls_rgw_client cls_refcount_client cls_log_client cls_statelog_client cls_timeindex_client cls_version_client cls_replica_log_client cls_user_client ceph-common common_utf8 global ${CURL_LIBRARIES} @@ -189,7 +189,7 @@ endif() add_executable(radosgw rgw_main.cc) target_link_libraries(radosgw radosgw_a librados - cls_rgw_client cls_lock_client cls_refcount_client + cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client cls_log_client cls_statelog_client cls_timeindex_client cls_version_client cls_replica_log_client cls_user_client global ${FCGI_LIBRARY} ${LIB_RESOLV} @@ -210,7 +210,7 @@ set(radosgw_admin_srcs rgw_orphan.cc) add_executable(radosgw-admin ${radosgw_admin_srcs}) target_link_libraries(radosgw-admin rgw_a librados - cls_rgw_client cls_lock_client cls_refcount_client + cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client cls_log_client cls_statelog_client cls_timeindex_client cls_version_client cls_replica_log_client cls_user_client global ${FCGI_LIBRARY} ${LIB_RESOLV} @@ -221,7 +221,7 @@ set(radosgw_es_srcs rgw_es_main.cc) add_executable(radosgw-es ${radosgw_es_srcs}) target_link_libraries(radosgw-es rgw_a librados - cls_rgw_client cls_lock_client cls_refcount_client + cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client cls_log_client cls_statelog_client cls_timeindex_client cls_version_client cls_replica_log_client cls_user_client global ${FCGI_LIBRARY} ${LIB_RESOLV} @@ -239,7 +239,7 @@ set(radosgw_object_expirer_srcs rgw_object_expirer.cc) add_executable(radosgw-object-expirer ${radosgw_object_expirer_srcs}) target_link_libraries(radosgw-object-expirer rgw_a librados - cls_rgw_client cls_lock_client cls_refcount_client + cls_rgw_client cls_otp_client cls_lock_client cls_refcount_client cls_log_client cls_statelog_client cls_timeindex_client cls_version_client cls_replica_log_client cls_user_client global ${FCGI_LIBRARY} ${LIB_RESOLV} @@ -254,6 +254,7 @@ target_link_libraries(rgw PRIVATE rgw_a librados cls_rgw_client + cls_otp_client cls_lock_client cls_refcount_client cls_log_client diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index ea9c4800627cd..95243a3a478fb 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -502,6 +502,11 @@ enum { OPT_RESHARD_STATUS, OPT_RESHARD_PROCESS, OPT_RESHARD_CANCEL, + OPT_MFA_CREATE, + OPT_MFA_REMOVE, + OPT_MFA_GET, + OPT_MFA_LIST, + OPT_MFA_CHECK, }; static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_cmd, bool *need_more) @@ -524,6 +529,7 @@ static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_ strcmp(cmd, "lc") == 0 || strcmp(cmd, "mdlog") == 0 || strcmp(cmd, "metadata") == 0 || + strcmp(cmd, "mfa") == 0 || strcmp(cmd, "object") == 0 || strcmp(cmd, "objects") == 0 || strcmp(cmd, "olh") == 0 || @@ -956,6 +962,17 @@ static int get_cmd(const char *cmd, const char *prev_cmd, const char *prev_prev_ return OPT_RESHARD_PROCESS; if (strcmp(cmd, "cancel") == 0) return OPT_RESHARD_CANCEL; + } else if (strcmp(prev_cmd, "mfa") == 0) { + if (strcmp(cmd, "create") == 0) + return OPT_MFA_CREATE; + if (strcmp(cmd, "remove") == 0) + return OPT_MFA_REMOVE; + if (strcmp(cmd, "get") == 0) + return OPT_MFA_GET; + if (strcmp(cmd, "list") == 0) + return OPT_MFA_LIST; + if (strcmp(cmd, "check") == 0) + return OPT_MFA_CHECK; } return -EINVAL; @@ -2546,6 +2563,12 @@ int main(int argc, const char **argv) boost::optional compression_type; + string totp_serial; + string totp_seed; + string totp_pin; + int totp_seconds = 0; + int totp_window = 0; + for (std::vector::iterator i = args.begin(); i != args.end(); ) { if (ceph_argparse_double_dash(args, i)) { break; @@ -2867,6 +2890,16 @@ int main(int argc, const char **argv) perm_policy_doc = val; } else if (ceph_argparse_witharg(args, i, &val, "--path-prefix", (char*)NULL)) { path_prefix = val; + } else if (ceph_argparse_witharg(args, i, &val, "--totp-serial", (char*)NULL)) { + totp_serial = val; + } else if (ceph_argparse_witharg(args, i, &val, "--totp-pin", (char*)NULL)) { + totp_pin = val; + } else if (ceph_argparse_witharg(args, i, &val, "--totp-seed", (char*)NULL)) { + totp_seed = val; + } else if (ceph_argparse_witharg(args, i, &val, "--totp-seconds", (char*)NULL)) { + totp_seconds = atoi(val.c_str()); + } else if (ceph_argparse_witharg(args, i, &val, "--totp-window", (char*)NULL)) { + totp_window = atoi(val.c_str()); } else if (strncmp(*i, "-", 1) == 0) { cerr << "ERROR: invalid flag " << *i << std::endl; return EINVAL; @@ -7261,5 +7294,150 @@ next: } } + if (opt_cmd == OPT_MFA_CREATE) { + rados::cls::otp::otp_info_t config; + + if (user_id.empty()) { + cerr << "ERROR: user id was not provided (via --uid)" << std::endl; + return EINVAL; + } + + if (totp_serial.empty()) { + cerr << "ERROR: TOTP device serial number was not provided (via --totp-serial)" << std::endl; + return EINVAL; + } + + if (totp_seed.empty()) { + cerr << "ERROR: TOTP device seed was not provided (via --totp-seed)" << std::endl; + return EINVAL; + } + + config.id = totp_serial; + config.seed = totp_seed; + + if (totp_seconds > 0) { + config.step_size = totp_seconds; + } + + if (totp_window > 0) { + config.window = totp_window; + } + + int ret = store->create_mfa(user_id, config); + if (ret < 0) { + cerr << "MFA creation failed, error: " << cpp_strerror(-ret) << std::endl; + return -ret; + } + + RGWUserInfo& user_info = user_op.get_user_info(); + user_info.mfa_ids.insert(totp_serial); + user_op.set_mfa_ids(user_info.mfa_ids); + string err; + ret = user.modify(user_op, &err); + if (ret < 0) { + cerr << "ERROR: failed storing user info, error: " << err << std::endl; + return -ret; + } + } + + if (opt_cmd == OPT_MFA_REMOVE) { + if (user_id.empty()) { + cerr << "ERROR: user id was not provided (via --uid)" << std::endl; + return EINVAL; + } + + if (totp_serial.empty()) { + cerr << "ERROR: TOTP device serial number was not provided (via --totp-serial)" << std::endl; + return EINVAL; + } + + int ret = store->remove_mfa(user_id, totp_serial); + if (ret < 0) { + cerr << "MFA removal failed, error: " << cpp_strerror(-ret) << std::endl; + return -ret; + } + + RGWUserInfo& user_info = user_op.get_user_info(); + user_info.mfa_ids.erase(totp_serial); + user_op.set_mfa_ids(user_info.mfa_ids); + string err; + ret = user.modify(user_op, &err); + if (ret < 0) { + cerr << "ERROR: failed storing user info, error: " << err << std::endl; + return -ret; + } + } + + if (opt_cmd == OPT_MFA_GET) { + if (user_id.empty()) { + cerr << "ERROR: user id was not provided (via --uid)" << std::endl; + return EINVAL; + } + + if (totp_serial.empty()) { + cerr << "ERROR: TOTP device serial number was not provided (via --totp-serial)" << std::endl; + return EINVAL; + } + + rados::cls::otp::otp_info_t result; + int ret = store->get_mfa(user_id, totp_serial, &result); + if (ret < 0) { + if (ret == -ENOENT || ret == -ENODATA) { + cerr << "MFA serial id not found" << std::endl; + } else { + cerr << "MFA retrieval failed, error: " << cpp_strerror(-ret) << std::endl; + } + return -ret; + } + formatter->open_object_section("result"); + encode_json("entry", result, formatter); + formatter->close_section(); + formatter->flush(cout); + } + + if (opt_cmd == OPT_MFA_LIST) { + if (user_id.empty()) { + cerr << "ERROR: user id was not provided (via --uid)" << std::endl; + return EINVAL; + } + + list result; + int ret = store->list_mfa(user_id, &result); + if (ret < 0) { + cerr << "MFA listing failed, error: " << cpp_strerror(-ret) << std::endl; + return -ret; + } + formatter->open_object_section("result"); + encode_json("entries", result, formatter); + formatter->close_section(); + formatter->flush(cout); + } + + if (opt_cmd == OPT_MFA_CHECK) { + if (user_id.empty()) { + cerr << "ERROR: user id was not provided (via --uid)" << std::endl; + return EINVAL; + } + + if (totp_serial.empty()) { + cerr << "ERROR: TOTP device serial number was not provided (via --totp-serial)" << std::endl; + return EINVAL; + } + + if (totp_pin.empty()) { + cerr << "ERROR: TOTP device serial number was not provided (via --totp-pin)" << std::endl; + return EINVAL; + } + + list result; + int ret = store->check_mfa(user_id, totp_serial, totp_pin); + if (ret < 0) { + cerr << "MFA check failed, error: " << cpp_strerror(-ret) << std::endl; + return -ret; + } + + cout << "ok" << std::endl; + } + return 0; } -- 2.39.5