]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mon/AuthMonitor: add key-type switch
authorPatrick Donnelly <pdonnell@ibm.com>
Fri, 21 Mar 2025 16:56:06 +0000 (12:56 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Mon, 13 Oct 2025 23:59:34 +0000 (19:59 -0400)
So it's possible to test with various key-types.

Signed-off-by: Patrick Donnelly <pdonnell@ibm.com>
(cherry picked from commit e8ce247d9267d2a453865c4b3d9692852d979b2a)

src/auth/Crypto.cc
src/auth/Crypto.h
src/common/options/mon.yaml.in
src/mon/AuthMonitor.cc
src/mon/AuthMonitor.h
src/mon/MonCommands.h
src/mon/Monitor.cc
src/tools/ceph_authtool.cc

index d77ceef2fdadc64d16e0a4c6631ec89c58f1ad7c..8ef4f5ae1f14baaba7bdd1fbec00be8998801789 100644 (file)
@@ -1137,6 +1137,9 @@ int CryptoManager::get_key_type(const std::string& s)
 {
   auto l = s;
   std::transform(l.begin(), l.end(), l.begin(), ::tolower);
+  if (l == "recommended") {
+    return CEPH_CRYPTO_AES256KRB5;
+  }
   if (l == "aes") {
     return CEPH_CRYPTO_AES;
   }
@@ -1149,6 +1152,12 @@ int CryptoManager::get_key_type(const std::string& s)
   return -ENOENT;
 }
 
+const std::set<int>& CryptoManager::get_secure_key_types()
+{
+  static const std::set<int> secure_keys{CEPH_CRYPTO_AES256KRB5};
+  return secure_keys;
+}
+
 bool CryptoManager::crypto_type_supported(int type) const
 {
   return supported_crypto_types.find(type) != supported_crypto_types.end();
index b9fbe0a26a507c2663830eb816af24db46a02465..d3b39a4382cd388d867796863d452f91467ebadb 100644 (file)
@@ -275,6 +275,7 @@ public:
   }
 
   static int get_key_type(const std::string& s);
+  static const std::set<int>& get_secure_key_types();
   bool crypto_type_supported(int type) const;
 
   std::shared_ptr<CryptoHandler> get_handler(int type);
index b6b7def19184d510b69740175e8b0d6bd9cc773e..4384757078db4a56ee25fa822316f072e525dd54 100644 (file)
@@ -755,6 +755,22 @@ options:
   services:
   - mon
   with_legacy: true
+- name: mon_auth_allow_insecure_key
+  type: bool
+  level: advanced
+  desc: Allow the creation of keys with insecure type.
+  long_desc: >
+    By default, the Monitors will allow creation of keys with a cipher type
+    known to be insecure so long as the Monitors also allow that cipher to
+    authenticate. When that cipher type is removed from the authentication
+    list, the Monitors will also disable the default value of this
+    configuration. When disabled, ceph commands can no longer create keys with
+    an insecure cipher type.
+  default: false
+  services:
+  - mon
+  flags:
+  - runtime
 - name: mon_auth_validate_all_caps
   type: bool
   level: advanced
index bbf32a7c83fd15cf49e623c6402b4ebc8055b3e9..d34681c0c9dc1e95d47e9e8ce8e7e1ef4bc7a8d3 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "auth/AuthServiceHandler.h"
 #include "auth/KeyRing.h"
+#include "auth/Crypto.h"
 #include "include/stringify.h"
 #include "include/ceph_assert.h"
 
 #include "mgr/MgrCap.h"
 #include "osd/OSDCap.h"
 
+#include <string>
+#include <string_view>
+using namespace std::literals::string_view_literals;
+using namespace std::literals::string_literals;
+
 #define dout_subsys ceph_subsys_mon
 #undef dout_prefix
 #define dout_prefix _prefix(_dout, mon, get_last_committed())
@@ -1358,6 +1364,22 @@ bool AuthMonitor::valid_caps(const map<string, string>& caps, ostream *out)
   return true;
 }
 
+int AuthMonitor::get_cipher_type(const cmdmap_t& cmdmap, std::ostream& ss) const
+{
+  std::string key_string_type;
+  cmd_getval_or<std::string>(cmdmap, "key_type"sv, key_string_type, "recommended"s);
+  auto key_type = CryptoManager::get_key_type(key_string_type);
+  auto&& secure_key_types = CryptoManager::get_secure_key_types();
+  if (!secure_key_types.contains(key_type)) {
+    if (!cct->_conf.get_val<bool>("mon_auth_allow_insecure_key")) {
+      ss << "creating key with insecure key type (\"" << key_string_type << "\") not allowed";
+      return -EPERM;
+    }
+  }
+  return key_type;
+}
+
+
 bool AuthMonitor::prepare_command(MonOpRequestRef op)
 {
   auto m = op->get_req<MMonCommand>();
@@ -1451,6 +1473,11 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
     bufferlist bl = m->get_data();
     bool has_keyring = (bl.length() > 0);
 
+    int key_type = get_cipher_type(cmdmap, ss);
+    if (key_type < 0) {
+      goto done;
+    }
+
     KeyRing new_keyring;
     if (has_keyring) {
       auto iter = bl.cbegin();
@@ -1513,7 +1540,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
     if (!has_keyring) {
       dout(10) << "AuthMonitor::prepare_command generating random key for "
         << auth_inc.name << dendl;
-      new_inc.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+      new_inc.key.create(g_ceph_context, key_type);
     }
     new_inc.caps = encoded_caps;
 
@@ -1541,6 +1568,11 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
       goto done;
     }
 
+    int key_type = get_cipher_type(cmdmap, ss);
+    if (key_type < 0) {
+      goto done;
+    }
+
     // is there an uncommitted pending_key? (or any change for this entity)
     for (auto& p : pending_auth) {
       if (p.inc_type == AUTH_DATA) {
@@ -1568,7 +1600,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
        auth_inc.op = KeyServerData::AUTH_INC_ADD;
        auth_inc.name = entity;
        auth_inc.auth = entity_auth;
-       auth_inc.auth.pending_key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+       auth_inc.auth.pending_key.create(g_ceph_context, key_type);
        push_cephx_inc(auth_inc);
        kr.add(entity, auth_inc.auth.key, auth_inc.auth.pending_key);
         push_cephx_inc(auth_inc);
@@ -1619,6 +1651,11 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
       goto done;
     }
 
+    int key_type = get_cipher_type(cmdmap, ss);
+    if (key_type < 0) {
+      goto done;
+    }
+
     // do we have it?
     EntityAuth entity_auth;
     if (mon.key_server.get_auth(entity, entity_auth)) {
@@ -1667,7 +1704,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
     KeyServerData::Incremental auth_inc;
     auth_inc.op = KeyServerData::AUTH_INC_ADD;
     auth_inc.name = entity;
-    auth_inc.auth.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+    auth_inc.auth.key.create(g_ceph_context, key_type);
     auth_inc.auth.caps = wanted_caps;
 
     push_cephx_inc(auth_inc);
@@ -1695,6 +1732,11 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
     string mds_cap_string, osd_cap_string;
     string osd_cap_wanted = "r";
 
+    int key_type = get_cipher_type(cmdmap, ss);
+    if (key_type < 0) {
+      goto done;
+    }
+
     const Filesystem* fs = nullptr;
     if (filesystem != "*" && filesystem != "all") {
       const auto& fsmap = mon.mdsmon()->get_fsmap();
@@ -1791,7 +1833,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
        dout(20) << it.first << " cap = \"" << it.second << "\"" << dendl;
       }
 
-      err = _update_caps(entity, newcaps, op, ss, ds, &rdata, f.get());
+      err = _update_caps(entity, key_type, newcaps, op, ss, ds, &rdata, f.get());
       if (err == 0) {
        return true;
       } else {
@@ -1799,14 +1841,14 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
       }
     }
 
-    err = _create_entity(entity, newcaps, op, ss, ds, &rdata, f.get());
+    err = _create_entity(entity, key_type, newcaps, op, ss, ds, &rdata, f.get());
     if (err == 0) {
       return true;
     } else {
       goto done;
     }
   } else if (prefix == "auth caps" && !entity_name.empty()) {
-    err = _update_caps(entity, ceph_caps, op, ss, ds, &rdata, f.get());
+    err = _update_caps(entity, CEPH_CRYPTO_AES256KRB5, ceph_caps, op, ss, ds, &rdata, f.get());
     if (err == 0) {
       return true;
     } else {
@@ -1833,6 +1875,11 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
       goto done;
     }
 
+    int key_type = get_cipher_type(cmdmap, ss);
+    if (key_type < 0) {
+      goto done;
+    }
+
     EntityAuth entity_auth;
     if (!mon.key_server.get_auth(entity, entity_auth)) {
       ss << "entity does not exist";
@@ -1840,7 +1887,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
       goto done;
     }
 
-    entity_auth.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+    entity_auth.key.create(g_ceph_context, key_type);
 
     KeyServerData::Incremental auth_inc;
     auth_inc.op = KeyServerData::AUTH_INC_ADD;
@@ -2011,6 +2058,7 @@ int AuthMonitor::_check_and_encode_caps(const map<string, string>& caps,
 // Pass both, rdata as well as fmtr, to enable printing of the key after
 // update
 int AuthMonitor::_update_or_create_entity(const EntityName& entity,
+  int key_type,
   const map<string, string>& caps, MonOpRequestRef op, stringstream& ss,
   stringstream& ds, bufferlist* rdata, Formatter* fmtr, bool create_entity)
 {
@@ -2039,7 +2087,7 @@ int AuthMonitor::_update_or_create_entity(const EntityName& entity,
   auth_inc.op = KeyServerData::AUTH_INC_ADD;
   auth_inc.auth.caps = encoded_caps;
   if (create_entity) {
-    auth_inc.auth.key.create(g_ceph_context, CEPH_CRYPTO_AES256KRB5);
+    auth_inc.auth.key.create(g_ceph_context, key_type);
   }
 
   push_cephx_inc(auth_inc);
@@ -2060,20 +2108,20 @@ int AuthMonitor::_update_or_create_entity(const EntityName& entity,
   return 0;
 }
 
-int AuthMonitor::_update_caps(const EntityName& entity,
+int AuthMonitor::_update_caps(const EntityName& entity, int key_type,
   const map<string, string>& caps, MonOpRequestRef op, stringstream& ss,
   stringstream& ds, bufferlist* rdata, Formatter* fmtr)
 {
-  return _update_or_create_entity(entity, caps, op, ss, ds, rdata, fmtr,
-                                 false);
+  return _update_or_create_entity(entity, key_type, caps, op, ss,
+                                  ds, rdata, fmtr, false);
 }
 
-int AuthMonitor::_create_entity(const EntityName& entity,
+int AuthMonitor::_create_entity(const EntityName& entity, int key_type,
   const map<string, string>& caps, MonOpRequestRef op, stringstream& ss,
   stringstream& ds, bufferlist* rdata, Formatter* fmtr)
 {
-  return _update_or_create_entity(entity, caps, op, ss, ds, rdata, fmtr,
-                                 true);
+  return _update_or_create_entity(entity, key_type, caps, op, ss,
+                                  ds, rdata, fmtr, true);
 }
 
 bool AuthMonitor::prepare_global_id(MonOpRequestRef op)
index 0495e20c479c33d0726ebb2ba0810b599ac8826c..7134612615dcd439b59e861ccd5cf6c82c64e2a7 100644 (file)
@@ -102,8 +102,9 @@ public:
 
 private:
   std::vector<Incremental> pending_auth;
-  uint64_t max_global_id;
-  uint64_t last_allocated_id;
+  uint64_t max_global_id = 0;
+  uint64_t last_allocated_id = 0;
+  boost::intrusive_ptr<CephContext> cct;
 
   // these are protected by mon->auth_lock
   int mon_num = 0, mon_rank = 0;
@@ -174,6 +175,8 @@ private:
   bool prep_auth(MonOpRequestRef op, bool paxos_writable);
 
   bool preprocess_command(MonOpRequestRef op);
+
+  int get_cipher_type(const cmdmap_t& cmdmap, std::ostream& ss) const;
   bool prepare_command(MonOpRequestRef op);
 
   void _encode_keyring(KeyRing& kr, const EntityName& entity,
@@ -189,15 +192,15 @@ private:
   int _check_and_encode_caps(const std::map<std::string, std::string>& caps,
     std::map<std::string, bufferlist>& encoded_caps, std::stringstream& ss);
 
-  int _update_or_create_entity(const EntityName& entity,
+  int _update_or_create_entity(const EntityName& entity, int key_type,
     const std::map<std::string, std::string>& caps, MonOpRequestRef op,
     std::stringstream& ss, std::stringstream& ds, bufferlist* rdata=nullptr,
     Formatter* fmtr=nullptr, bool create_entity=false);
-  int _create_entity(const EntityName& entity,
+  int _create_entity(const EntityName& entity, int key_type,
     const std::map<std::string, std::string>& caps, MonOpRequestRef op,
     std::stringstream& ss, std::stringstream& ds, bufferlist* rdata,
     Formatter* fmtr);
-  int _update_caps(const EntityName& entity,
+  int _update_caps(const EntityName& entity, int key_type,
     const std::map<std::string, std::string>& caps, MonOpRequestRef op,
     std::stringstream& ss, std::stringstream& ds, bufferlist* rdata,
     Formatter* fmtr);
@@ -229,10 +232,8 @@ private:
       const EntityAuth& auth);
 
  public:
-  AuthMonitor(Monitor &mn, Paxos &p, const std::string& service_name)
-    : PaxosService(mn, p, service_name),
-      max_global_id(0),
-      last_allocated_id(0)
+  AuthMonitor(CephContext* cct, Monitor &mn, Paxos &p, const std::string& service_name)
+    : PaxosService(mn, p, service_name), cct(cct)
   {}
 
   void pre_auth(MAuth *m);
index 2c0ab671efdb19254e9f70ae847ed32e8f7080c7..0892c6a15036c6dd5d4119f5f43e5d71d123fd30 100644 (file)
@@ -157,24 +157,36 @@ COMMAND_WITH_FLAG("auth list", "list authentication state", "auth", "rx",
 COMMAND("auth ls", "list authentication state", "auth", "rx")
 COMMAND("auth import", "auth import: read keyring file from -i <file>",
        "auth", "rwx")
-COMMAND("auth add "
-       "name=entity,type=CephString "
-       "name=caps,type=CephString,n=N,req=false",
+COMMAND("auth add"
+       " name=entity,type=CephString"
+       " name=caps,type=CephString,n=N,req=false"
+        " --"
+       " name=key_type,type=CephString,req=false"
+        ,
        "add auth info for <entity> from input file, or random key if no "
         "input is given, and/or any caps specified in the command",
        "auth", "rwx")
-COMMAND("auth rotate "
-       "name=entity,type=CephString",
+COMMAND("auth rotate"
+       " name=entity,type=CephString"
+        " --"
+       " name=key_type,type=CephString,req=false"
+        ,
        "rotate entity key",
        "auth", "rwx")
-COMMAND("auth get-or-create-key "
-       "name=entity,type=CephString "
-       "name=caps,type=CephString,n=N,req=false",
+COMMAND("auth get-or-create-key"
+       " name=entity,type=CephString"
+       " name=caps,type=CephString,n=N,req=false"
+        " --"
+       " name=key_type,type=CephString,req=false"
+        ,
        "get, or add, key for <name> from system/caps pairs specified in the command.  If key already exists, any given caps must match the existing caps for that key.",
        "auth", "rwx")
-COMMAND("auth get-or-create "
-       "name=entity,type=CephString "
-       "name=caps,type=CephString,n=N,req=false",
+COMMAND("auth get-or-create"
+       " name=entity,type=CephString"
+       " name=caps,type=CephString,n=N,req=false"
+        " --"
+       " name=key_type,type=CephString,req=false"
+        ,
        "add auth info for <entity> from input file, or random key if no input given, and/or any caps specified in the command",
        "auth", "rwx")
 COMMAND("auth get-or-create-pending "
@@ -189,10 +201,13 @@ COMMAND("auth commit-pending "
        "name=entity,type=CephString",
        "rotate pending key into active position",
        "auth", "rwx")
-COMMAND("fs authorize "
-   "name=filesystem,type=CephString "
-   "name=entity,type=CephString "
-       "name=caps,type=CephString,n=N",
+COMMAND("fs authorize"
+        " name=filesystem,type=CephString"
+        " name=entity,type=CephString"
+       " name=caps,type=CephString,n=N"
+        " --"
+       " name=key_type,type=CephString,req=false"
+        ,
        "add auth for <entity> to access file system <filesystem> based on following directory and permissions pairs",
        "auth", "rwx")
 COMMAND("auth caps "
index f6495c7535ffe43a073e9ce81da080d5aa647e68..2a94004401222bafd36ae8453715e4ad5bdb05a1 100644 (file)
@@ -241,7 +241,7 @@ Monitor::Monitor(CephContext* cct_, string nm, MonitorDBStore *s,
   paxos_service[PAXOS_MONMAP].reset(new MonmapMonitor(*this, *paxos, "monmap"));
   paxos_service[PAXOS_OSDMAP].reset(new OSDMonitor(cct, *this, *paxos, "osdmap"));
   paxos_service[PAXOS_LOG].reset(new LogMonitor(*this, *paxos, "logm"));
-  paxos_service[PAXOS_AUTH].reset(new AuthMonitor(*this, *paxos, "auth"));
+  paxos_service[PAXOS_AUTH].reset(new AuthMonitor(cct, *this, *paxos, "auth"));
   paxos_service[PAXOS_MGR].reset(new MgrMonitor(*this, *paxos, "mgr"));
   paxos_service[PAXOS_MGRSTAT].reset(new MgrStatMonitor(*this, *paxos, "mgrstat"));
   paxos_service[PAXOS_HEALTH].reset(new HealthMonitor(*this, *paxos, "health"));
index dd5bff7e5f158dec335e0f1711e8fb64359a69e2..e53f3afa128f8d6b22854adc202c1dfa50d8d55f 100644 (file)
@@ -66,7 +66,7 @@ int main(int argc, const char **argv)
   map<string,bufferlist> caps;
   std::string fn;
 
-  int key_type = CEPH_CRYPTO_AES256KRB5;
+  int key_type = CryptoManager::get_key_type("recommended");
 
   if (args.empty()) {
     cerr << argv[0] << ": -h or --help for usage" << std::endl;