From: Patrick Donnelly Date: Wed, 26 Mar 2025 01:59:34 +0000 (-0400) Subject: mon/AuthMonitor: add dump-keys and wipe-rotating-service-keys X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=f90cbe291b1e6e5a6802a5f9b6cefa2f57fc3fb2;p=ceph-ci.git mon/AuthMonitor: add dump-keys and wipe-rotating-service-keys `auth dump-keys` allows examining the key types for each entity and also the rotating session keys. This lets us confirm key upgrades are done as expected. `wipe-rotating-service-keys` clears out existing non-auth service keys so that we do not need to wait for the rotating key expiration. It is not disruptive so long as clients renew their tickets when prompted by the auth epoch change. Signed-off-by: Patrick Donnelly --- diff --git a/src/auth/cephx/CephxKeyServer.cc b/src/auth/cephx/CephxKeyServer.cc index 49813ef320d..3ad566a7822 100644 --- a/src/auth/cephx/CephxKeyServer.cc +++ b/src/auth/cephx/CephxKeyServer.cc @@ -382,7 +382,7 @@ void KeyServer::encode_plaintext(bufferlist &bl) bl.append(os.str()); } -bool KeyServer::prepare_rotating_update(bufferlist& rotating_bl) +bool KeyServer::prepare_rotating_update(bufferlist& rotating_bl, bool wipe) { std::scoped_lock l{lock}; ldout(cct, 20) << __func__ << " before: data.rotating_ver=" << data.rotating_ver @@ -390,7 +390,19 @@ bool KeyServer::prepare_rotating_update(bufferlist& rotating_bl) KeyServerData pending_data(nullptr); pending_data.rotating_ver = data.rotating_ver + 1; - pending_data.rotating_secrets = data.rotating_secrets; + if (wipe) { + /* Always keep CEPH_ENTITY_TYPE_AUTH: existing auth service keys are needed + * to renew tickets by daemons/clients and the only information in an old + * ticket used is the global_id. Forging tickets is not a significant + * concern. A stolen auth service key is not worthwhile since you would + * be incaapable of generating useful service tickets with the associated + * service key (e.g. "osd"). + */ + RotatingSecrets& r = data.rotating_secrets[CEPH_ENTITY_TYPE_AUTH]; + pending_data.rotating_secrets[CEPH_ENTITY_TYPE_AUTH] = r; + } else { + pending_data.rotating_secrets = data.rotating_secrets; + } int added = 0; added += _rotate_secret(CEPH_ENTITY_TYPE_AUTH, pending_data); diff --git a/src/auth/cephx/CephxKeyServer.h b/src/auth/cephx/CephxKeyServer.h index ebc496eccae..c492656c498 100644 --- a/src/auth/cephx/CephxKeyServer.h +++ b/src/auth/cephx/CephxKeyServer.h @@ -344,7 +344,7 @@ public: } } - bool prepare_rotating_update(ceph::buffer::list& rotating_bl); + bool prepare_rotating_update(ceph::buffer::list& rotating_bl, bool wipe); bool get_rotating_encrypted(const EntityName& name, ceph::buffer::list& enc_bl) const; diff --git a/src/mon/AuthMonitor.cc b/src/mon/AuthMonitor.cc index d34681c0c9d..3326070ec17 100644 --- a/src/mon/AuthMonitor.cc +++ b/src/mon/AuthMonitor.cc @@ -79,7 +79,7 @@ bool AuthMonitor::check_rotate() { KeyServerData::Incremental rot_inc; rot_inc.op = KeyServerData::AUTH_INC_SET_ROTATING; - if (mon.key_server.prepare_rotating_update(rot_inc.rotating_bl)) { + if (mon.key_server.prepare_rotating_update(rot_inc.rotating_bl, false)) { dout(10) << __func__ << " updating rotating" << dendl; push_cephx_inc(rot_inc); return true; @@ -865,6 +865,8 @@ bool AuthMonitor::preprocess_command(MonOpRequestRef op) cmd_getval(cmdmap, "prefix", prefix); if (prefix == "auth add" || prefix == "auth rotate" || + prefix == "auth dump-keys" || + prefix == "auth wipe-rotating-service-keys" || prefix == "auth del" || prefix == "auth rm" || prefix == "auth get-or-create" || @@ -1899,6 +1901,30 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op) wait_for_commit(op, new Monitor::C_Command(mon, op, 0, rs, rdata, get_last_committed() + 1)); return true; + } else if (prefix == "auth dump-keys") { + if (f) { + f->open_object_section("keys"); + mon.key_server.dump(f.get()); + f->close_section(); + f->flush(ds); + err = 0; + } else { + err = -EINVAL; + } + goto done; + } else if (prefix == "auth wipe-rotating-service-keys") { + /* N.B.: doing this requires all service daemons to restart to get new service keys. */ + /* is this true?? */ + KeyServerData::Incremental rot_inc; + rot_inc.op = KeyServerData::AUTH_INC_SET_ROTATING; + bool modified = mon.key_server.prepare_rotating_update(rot_inc.rotating_bl, true); + ceph_assert(modified); + rs = "wiped rotating service keys!"; + dout(5) << __func__ << " wiped rotating service keys!" << dendl; + push_cephx_inc(rot_inc); + wait_for_commit(op, new Monitor::C_Command(mon, op, 0, rs, rdata, + get_last_committed() + 1)); + return true; } done: rdata.append(ds); diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 04e91f386a4..9b6bb4aa86e 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -177,6 +177,12 @@ COMMAND("auth rotate" , "rotate entity key", "auth", "rwx") +COMMAND("auth dump-keys", + "dump keys", + "auth", "rwx") +COMMAND("auth wipe-rotating-service-keys", + "wipe rotating keys", + "auth", "rwx") COMMAND("auth get-or-create-key" " name=entity,type=CephString" " name=caps,type=CephString,n=N,req=false" diff --git a/src/tools/ceph_monstore_tool.cc b/src/tools/ceph_monstore_tool.cc index 5bb0ece595e..d3a0d309057 100644 --- a/src/tools/ceph_monstore_tool.cc +++ b/src/tools/ceph_monstore_tool.cc @@ -506,7 +506,7 @@ static int update_auth(MonitorDBStore& st, const string& keyring_path) KeyServer ks(g_ceph_context, nullptr); KeyServerData::Incremental auth_inc; auth_inc.op = KeyServerData::AUTH_INC_SET_ROTATING; - bool r = ks.prepare_rotating_update(auth_inc.rotating_bl); + bool r = ks.prepare_rotating_update(auth_inc.rotating_bl, false); ceph_assert(r); AuthMonitor::Incremental inc; inc.inc_type = AuthMonitor::AUTH_DATA;