]> git.apps.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>
Wed, 1 Oct 2025 18:46:57 +0000 (14:46 -0400)
`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 49813ef320d08e728340f98d758a76eacb0c5fbe..3ad566a7822bd767dd12e3891cff49c68231edaa 100644 (file)
@@ -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);
index ebc496eccaeab5c8f415975a7edc1d2fb36e8987..c492656c498604a7cf37cb350706d3998732b4be 100644 (file)
@@ -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;
 
index d34681c0c9dc1e95d47e9e8ce8e7e1ef4bc7a8d3..3326070ec17e5f7934f5d61c39dc9e23a19eef82 100644 (file)
@@ -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);
index 04e91f386a42f9eb10cf400730035cbae2d87fcb..9b6bb4aa86eee925352f4ba561f494883d999cee 100644 (file)
@@ -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"
index 5bb0ece595ecc8d947156f7d047fa35659289999..d3a0d309057819304671e8ab3be27a67f1ead605 100644 (file)
@@ -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;