From 01c52b1eae929e86fc7777ba3fcff544c5aba8af Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Thu, 25 Mar 2021 20:59:13 +0100 Subject: [PATCH] mon: fail fast when unauthorized global_id (re)use is disallowed When unauthorized global_id (re)use is disallowed, we don't want to let unpatched clients in because they wouldn't be able to reestablish their monitor session later, resulting in subtle hangs and disrupted user workloads. Denying the initial connect for all legacy (CephXAuthenticate < v3) clients is not feasible because a large subset of them never stopped presenting their ticket on reconnects and are therefore compatible with enforcing mode: most notably all kernel clients but also pre-luminous userspace clients. They don't need to be patched and excluding them would significantly hamper the adoption of enforcing mode. Instead, force clients that we are not sure about to reconnect shortly after they go through authentication and obtain global_id. This is done in Monitor::dispatch_op() to capture both msgr1 and msgr2, most likely instead of dispatching mon_subscribe. We need to let mon_getmap through for "ceph ping" and "ceph tell" to work. This does mean that we share the monmap, which lets the client return from MonClient::authenticate() considering authentication to be finished and causing the potential reconnect error to not propagate to the user -- the client would hang waiting for remaining cluster maps. For msgr1, this is unavoidable because the monmap is sent immediately after the final MAuthReply. But for msgr2 this is rare: most of the time we get to their mon_subscribe and cut the connection before they process the monmap! Regardless, the user doesn't get a chance to start a workload since there is no proper higher-level session at that point. To help with identifying clients that need patching, add global_id and global_id_status to "sessions" output. Signed-off-by: Ilya Dryomov (cherry picked from commit 08766a17edebb7450cd9b17cc2dc01efc068bb94) Conflicts: src/mon/Monitor.cc [ commit e1163b445bbf ("mon: print entity_name along with caps to debug log") not in nautilus ] --- src/auth/AuthServiceHandler.cc | 23 ++++++++++++++++++++++ src/auth/AuthServiceHandler.h | 3 +++ src/common/legacy_config_opts.h | 1 + src/common/options.cc | 9 ++++++++- src/mon/Monitor.cc | 35 ++++++++++++++++++++++++++++++++- src/mon/Session.h | 4 ++++ 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/auth/AuthServiceHandler.cc b/src/auth/AuthServiceHandler.cc index fa46748d139eb..742b307b28bcf 100644 --- a/src/auth/AuthServiceHandler.cc +++ b/src/auth/AuthServiceHandler.cc @@ -23,6 +23,29 @@ #define dout_subsys ceph_subsys_auth +std::ostream& operator<<(std::ostream& os, + global_id_status_t global_id_status) +{ + switch (global_id_status) { + case global_id_status_t::NONE: + return os << "none"; + case global_id_status_t::NEW_PENDING: + return os << "new_pending"; + case global_id_status_t::NEW_OK: + return os << "new_ok"; + case global_id_status_t::NEW_NOT_EXPOSED: + return os << "new_not_exposed"; + case global_id_status_t::RECLAIM_PENDING: + return os << "reclaim_pending"; + case global_id_status_t::RECLAIM_OK: + return os << "reclaim_ok"; + case global_id_status_t::RECLAIM_INSECURE: + return os << "reclaim_insecure"; + default: + ceph_abort(); + } +} + int AuthServiceHandler::start_session(const EntityName& entity_name, uint64_t global_id, bool is_new_global_id, diff --git a/src/auth/AuthServiceHandler.h b/src/auth/AuthServiceHandler.h index 43b021983b273..6bd50bf841937 100644 --- a/src/auth/AuthServiceHandler.h +++ b/src/auth/AuthServiceHandler.h @@ -41,6 +41,9 @@ enum class global_id_status_t { RECLAIM_INSECURE }; +std::ostream& operator<<(std::ostream& os, + global_id_status_t global_id_status); + struct AuthServiceHandler { protected: CephContext *cct; diff --git a/src/common/legacy_config_opts.h b/src/common/legacy_config_opts.h index 7a89f34759f4b..1ff14bd61bd57 100644 --- a/src/common/legacy_config_opts.h +++ b/src/common/legacy_config_opts.h @@ -342,6 +342,7 @@ OPTION(cephx_sign_messages, OPT_BOOL) // Default to signing session messages if OPTION(auth_mon_ticket_ttl, OPT_DOUBLE) OPTION(auth_service_ticket_ttl, OPT_DOUBLE) OPTION(auth_allow_insecure_global_id_reclaim, OPT_BOOL) +OPTION(auth_expose_insecure_global_id_reclaim, OPT_BOOL) OPTION(auth_debug, OPT_BOOL) // if true, assert when weird things happen OPTION(mon_client_hunt_parallel, OPT_U32) // how many mons to try to connect to in parallel during hunt OPTION(mon_client_hunt_interval, OPT_DOUBLE) // try new mon every N seconds until we connect diff --git a/src/common/options.cc b/src/common/options.cc index 145e4cc9b6091..9cf884b265eb9 100644 --- a/src/common/options.cc +++ b/src/common/options.cc @@ -2268,7 +2268,14 @@ std::vector