]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mon/AuthMonitor: add dump-keys and wipe-rotating-service-keys
authorPatrick Donnelly <pdonnell@ibm.com>
Wed, 26 Mar 2025 01:59:34 +0000 (21:59 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Mon, 29 Dec 2025 22:29:59 +0000 (17:29 -0500)
`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 <pdonnell@ibm.com>
src/auth/cephx/CephxKeyServer.cc
src/auth/cephx/CephxKeyServer.h
src/mon/AuthMonitor.cc
src/mon/MonCommands.h
src/tools/ceph_monstore_tool.cc

index c97297fb9b4c34e3c604f9a44d15488805bff178..2430c291bfefbcaa6550f1cdced44ffe4746c221 100644 (file)
@@ -383,7 +383,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
@@ -391,7 +391,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);
index 5fb7608af6702a2365d79f8fa96c713f35ce872e..ffb0e58a29baf94d459cc62664e0acb48c311d95 100644 (file)
@@ -345,7 +345,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;
 
index d8b3b83f7c76440156359e1278db2f4d34baeba7..4ec1a9c342092ba7103261efc93ae177977a1af2 100644 (file)
@@ -80,7 +80,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;
@@ -866,6 +866,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" ||
@@ -1900,6 +1902,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);
index 17f12e4af7af0a85634b1c180d47a123413b0625..6c520d0ff49ee41e9c2ab98fffe2f90753bab699 100644 (file)
@@ -178,6 +178,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"
index 31ed80882d3499b5498337998b71ca6e5200fb1c..6b372e67b8f3ddac0fa833cc2582605eddadbe90 100644 (file)
@@ -507,7 +507,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;