]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mon: convert auth configs to monmap settings
authorPatrick Donnelly <pdonnell@ibm.com>
Fri, 6 Jun 2025 19:51:53 +0000 (15:51 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Wed, 1 Oct 2025 18:47:13 +0000 (14:47 -0400)
This serves a few purposes:

- Makes sure mons agreen on these settings (cannot have differing configs)
- Allows us to set secure defaults for a brand new cluster.

Signed-off-by: Patrick Donnelly <pdonnell@ibm.com>
17 files changed:
qa/suites/rados/upgrade/cephx/X/tasks/1-ceph.yaml
src/auth/Crypto.cc
src/auth/cephx/CephxKeyServer.cc
src/auth/cephx/CephxKeyServer.h
src/auth/cephx/CephxServiceHandler.cc
src/auth/cephx/CephxServiceHandler.h
src/common/options/global.yaml.in
src/mon/AuthMonitor.cc
src/mon/MonCommands.h
src/mon/MonMap.cc
src/mon/MonMap.h
src/mon/Monitor.cc
src/mon/Monitor.h
src/mon/MonmapMonitor.cc
src/mon/OSDMonitor.cc
src/tools/ceph_authtool.cc
src/tools/monmaptool.cc

index eefb7a26c4e6dac2adcc204901cacb9f53234aac..da3d0fc0f5557889f462d6b3af23a5e4fd8eccfd 100644 (file)
@@ -3,7 +3,6 @@ tasks:
     cluster-conf:
       global:
         auth service cipher: aes
-        cephx preferred cipher: aes
       mon:
         mon auth allow insecure key: true
     cephx:
index d39f3ffbe9eca764af86039e6d6ccd0b7031ba1c..b87bfa4f2fdd9c052248cad2b1cd6871e8707a7f 100644 (file)
@@ -1148,9 +1148,6 @@ 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;
   }
index 0d63948675473f8de75586b1121a7022519cd04e..6d5c58bd43d1c790cae28a275acbc346e5addf62 100644 (file)
@@ -147,15 +147,16 @@ bool KeyServerData::get_caps(CephContext *cct, const EntityName& name,
 
 #undef dout_prefix
 #define dout_prefix *_dout << "cephx keyserver: "
-
+#define cct kscct.get()
 
 KeyServer::KeyServer(CephContext *cct_, KeyRing *extra_secrets)
-  : cct(cct_),
+  : kscct(cct_),
     data(extra_secrets),
     lock{ceph::make_mutex("KeyServer::lock")}
 {
 }
 
+
 int KeyServer::start_server()
 {
   std::scoped_lock l{lock};
@@ -192,8 +193,9 @@ int KeyServer::_rotate_secret(uint32_t service_id, KeyServerData &pending_data)
 
   double const auth_mon_ticket_ttl = cct->_conf.get_val<double>("auth_mon_ticket_ttl");
   double const auth_service_ticket_ttl= cct->_conf.get_val<double>("auth_service_ticket_ttl");
-  auto const auth_service_cipher = cct->_conf.get_val<string>("auth_service_cipher");
-  const int auth_service_cipher_key_type = CryptoManager::get_key_type(auth_service_cipher);
+  auto const auth_service_cipher_key_type = get_service_cipher();
+  auto auth_service_cipher = CryptoManager::get_key_type_name(auth_service_cipher_key_type);
+  //const int auth_service_cipher_key_type = CryptoManager::get_key_type(auth_service_cipher);
 
   ldout(cct, 10) << __func__
           << ": auth_mon_ticket_ttl=" << auth_mon_ticket_ttl
index c97d5cf08027ad7833a387e42090f790697b6bbb..2cd3bdfbf4d7962d4fc4f81b75df7d6cc81a058e 100644 (file)
@@ -20,6 +20,8 @@
 #include <map>
 #include <string>
 
+#include <boost/intrusive_ptr.hpp>
+
 #include "auth/KeyRing.h"
 #include "CephxProtocol.h"
 #include "common/ceph_json.h"
@@ -242,7 +244,7 @@ WRITE_CLASS_ENCODER(KeyServerData::Incremental)
 
 
 class KeyServer : public KeyStore {
-  CephContext *cct;
+  boost::intrusive_ptr<CephContext> kscct;
   KeyServerData data;
   std::map<EntityName, CryptoKey> used_pending_keys;
   mutable ceph::mutex lock;
@@ -377,6 +379,16 @@ public:
   { return data.secrets_begin(); }
   std::map<EntityName, EntityAuth>::iterator secrets_end()
   { return data.secrets_end(); }
+
+  virtual int get_service_cipher() const {
+    return CEPH_CRYPTO_AES256KRB5;
+  }
+  virtual bool is_cipher_allowed(int cipher) const {
+    return cipher == CEPH_CRYPTO_AES256KRB5;
+  }
+  virtual std::vector<int> get_ciphers_allowed() const {
+    return {CEPH_CRYPTO_AES256KRB5};
+  }
 };
 WRITE_CLASS_ENCODER(KeyServer)
 
index 8ed135822a3c6eedff1478e5c8a4e91ec05bc0d1..07957fa274b4d9df384f68101118247dab3e7d01 100644 (file)
@@ -39,39 +39,15 @@ using ceph::decode;
 using ceph::encode;
 
 CephxServiceHandler::CephxServiceHandler(CephContext *cct_, KeyServer *ks)
-  : AuthServiceHandler(cct_), key_server(ks), server_challenge(0) {
-  cct->_conf.add_observer(this);
-  init_conf(cct->_conf);
-}
-
-std::vector<std::string> CephxServiceHandler::get_tracked_keys() const noexcept
+  : AuthServiceHandler(cct_)
+  , key_server(ks)
 {
-  static constexpr auto as_sv = std::to_array<std::string_view>({
-    "cephx_allowed_ciphers",
-  });
-  static_assert(std::is_sorted(as_sv.begin(), as_sv.end()), "keys are not sorted!");
-  return {as_sv.begin(), as_sv.end()};
-}
-
-void CephxServiceHandler::init_conf(const ConfigProxy& conf) {
-  std::unique_lock wl(lock);
-  auto s = conf.get_val<std::string>("cephx_allowed_ciphers");
-
-  std::vector<std::string> v;
-  get_str_vec(s, ", ", v);
-
-  for (auto& cipher : v) {
-    int cipher_type = CryptoManager::get_key_type(cipher);
-    if (cipher_type > 0) {
-      allowed_ciphers.insert(cipher_type);
-    }
-  }
 }
 
 bool CephxServiceHandler::cipher_is_allowed(int cipher)
 {
   std::shared_lock rl(lock);
-  return (allowed_ciphers.find(cipher) != allowed_ciphers.end());
+  return key_server->is_cipher_allowed(cipher);
 }
 
 int CephxServiceHandler::do_start_session(
@@ -217,7 +193,18 @@ int CephxServiceHandler::handle_request(
       }
 
       if (!cipher_is_allowed(eauth.key.get_type())) {
-       ldout(cct, 20) << __func__ << " authentication failed due to unallowed cipher type: " << eauth.key.get_type() << dendl;
+       ldout(cct, 20) << __func__
+                       << " authentication failed due to unallowed cipher type: "
+                       << CryptoManager::get_key_type_name(eauth.key.get_type()) << dendl;
+        ldout(cct, 30);
+          std::shared_lock rl(lock);
+          auto ciphers = key_server->get_ciphers_allowed();
+          dout_prefix << __func__
+                      << ": ciphers are:";
+          for (auto& cipher : ciphers) {
+            dout_prefix << " " << CryptoManager::get_key_type_name(cipher);
+          }
+        dout_prefix << dendl;
         ret = -EACCES;
         break;
       }
index 0ab15896e8252f2cfe093fb226dba9945b0791bc..3d9bc2cd183492aee8939495029d7c993f3819c6 100644 (file)
 #include "auth/Auth.h"
 
 #include "common/ceph_mutex.h"
-#include "common/config_obs.h"
 
 class KeyServer;
 struct CephXAuthenticate;
 struct CephXServiceTicketInfo;
 
-class CephxServiceHandler  : public AuthServiceHandler, md_config_obs_t {
+class CephxServiceHandler  : public AuthServiceHandler {
   KeyServer *key_server;
-  uint64_t server_challenge;
+  uint64_t server_challenge = 0;
 
-  std::set<int> allowed_ciphers;
   ceph::shared_mutex lock = ceph::make_shared_mutex("CephxServiceHandler::lock");
 
 public:
@@ -55,14 +53,6 @@ private:
   void build_cephx_response_header(int request_type, int status,
                                   ceph::buffer::list& bl);
 
-  std::vector<std::string> get_tracked_keys() const noexcept final;
-
-  void init_conf(const ConfigProxy& conf);
-  void handle_conf_change(const ConfigProxy& conf,
-                          const std::set <std::string> &changed) override {
-    init_conf(conf);
-  }
-
   bool cipher_is_allowed(int type);
 };
 
index e5ea60e79234258a51c378c490524d85ba960930..3306bdfade4870666026a6ae77debf79de6bfce0 100644 (file)
@@ -2170,23 +2170,6 @@ options:
    Ceph services. Valid settings are ``cephx`` or ``none``.
   default: cephx
   with_legacy: true
-- name: auth_service_cipher
-  type: str
-  level: advanced
-  desc: cipher type that is used to encrypt service tickets.
-  fmt_desc: When service tickets are being generaeted, this would
-   be the cipher that will be used to encrypt them. This requires
-   that all the services support the specific cipher. Valid settings
-   are ``aes` or ``aes256k``.
-  default: aes
-  services:
-  - mon
-  enum_values:
-  - aes
-  - aes256k
-  with_legacy: false
-  flags:
-  - runtime
 # what clients require of daemons
 - name: auth_client_required
   type: str
@@ -2271,24 +2254,6 @@ options:
   fmt_desc: If the Ceph version supports message signing, Ceph will sign
    all messages so they are more difficult to spoof.
   with_legacy: true
-- name: cephx_preferred_cipher
-  type: str
-  level: dev
-  desc: preferred cipher to use for new authentication keys
-  default: recommended
-  flags:
-  - runtime
-- name: cephx_allowed_ciphers
-  type: str
-  level: advanced
-  desc: list of allowed ciphers in cephx authentication
-  fmt_desc: This can be used to enable/disable specific key types
-   that are being used for connecting different entities to the
-   cluster.
-  default: aes, aes256k
-  with_legacy: false
-  flags:
-  - runtime
 - name: auth_mon_ticket_ttl
   type: float
   level: advanced
index 8b4b6e531c5141850f0ef22881d2fa9e4fa80fc2..8a8c484f7f6f6c41723c02135d6562de9120583a 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, false)) {
+  if (mon.prepare_rotating_update(rot_inc.rotating_bl, false)) {
     dout(10) << __func__ << " updating rotating" << dendl;
     push_cephx_inc(rot_inc);
     return true;
@@ -97,7 +97,7 @@ void AuthMonitor::process_used_pending_keys(
     inc.op = KeyServerData::AUTH_INC_ADD;
     inc.name = name;
 
-    mon.key_server.get_auth(name, inc.auth);
+    mon.get_auth(name, inc.auth);
     for (auto& p : pending_auth) {
       if (p.inc_type == AUTH_DATA) {
        KeyServerData::Incremental auth_inc;
@@ -150,7 +150,7 @@ void AuthMonitor::tick()
   }
 
   if (mon.monmap->min_mon_release >= ceph_release_t::quincy) {
-    auto used_pending_keys = mon.key_server.get_used_pending_keys();
+    auto used_pending_keys = mon.get_used_pending_keys();
     if (!used_pending_keys.empty()) {
       dout(10) << __func__ << " " << used_pending_keys.size() << " used pending_keys"
               << dendl;
@@ -191,8 +191,8 @@ void AuthMonitor::on_active()
   if (!mon.is_leader())
     return;
 
-  mon.key_server.start_server();
-  mon.key_server.clear_used_pending_keys();
+  mon.start_server();
+  mon.clear_used_pending_keys();
 
   if (is_writeable()) {
     bool propose = false;
@@ -302,7 +302,7 @@ void AuthMonitor::create_initial()
   dout(10) << "create_initial -- creating initial map" << dendl;
 
   // initialize rotating keys
-  mon.key_server.clear_secrets();
+  mon.clear_secrets();
   check_rotate();
   ceph_assert(pending_auth.size() == 1);
 
@@ -331,7 +331,7 @@ void AuthMonitor::update_from_paxos(bool *need_bootstrap)
   dout(10) << __func__ << dendl;
 
   version_t version = get_last_committed();
-  version_t keys_ver = mon.key_server.get_ver();
+  version_t keys_ver = mon.get_ver();
   if (version == keys_ver)
     return;
   ceph_assert(version > keys_ver);
@@ -352,12 +352,12 @@ void AuthMonitor::update_from_paxos(bool *need_bootstrap)
     __u8 struct_v;
     decode(struct_v, p);
     decode(max_global_id, p);
-    decode(mon.key_server, p);
-    mon.key_server.set_ver(latest_full);
+    decode(mon, p);
+    mon.set_ver(latest_full);
     keys_ver = latest_full;
   }
 
-  dout(10) << __func__ << " key server version " << mon.key_server.get_ver() << dendl;
+  dout(10) << __func__ << " key server version " << mon.get_ver() << dendl;
 
   // walk through incrementals
   while (version > keys_ver) {
@@ -370,7 +370,7 @@ void AuthMonitor::update_from_paxos(bool *need_bootstrap)
     // keys in here temporarily for bootstrapping that we need to
     // clear out.
     if (keys_ver == 0)
-      mon.key_server.clear_secrets();
+      mon.clear_secrets();
 
     dout(20) << __func__ << " walking through version " << (keys_ver+1)
              << " len " << bl.length() << dendl;
@@ -391,14 +391,14 @@ void AuthMonitor::update_from_paxos(bool *need_bootstrap)
           KeyServerData::Incremental auth_inc;
           auto iter = inc.auth_data.cbegin();
           decode(auth_inc, iter);
-          mon.key_server.apply_data_incremental(auth_inc);
+          mon.apply_data_incremental(auth_inc);
           break;
         }
       }
     }
 
     keys_ver++;
-    mon.key_server.set_ver(keys_ver);
+    mon.set_ver(keys_ver);
 
     if (keys_ver == 1 && mon.is_keyring_required()) {
       auto t(std::make_shared<MonitorDBStore::Transaction>());
@@ -420,7 +420,7 @@ void AuthMonitor::update_from_paxos(bool *need_bootstrap)
           << " format_version " << format_version
           << dendl;
 
-  mon.key_server.dump();
+  mon.dump();
 }
 
 bool AuthMonitor::_should_increase_max_global_id()
@@ -483,7 +483,7 @@ bool AuthMonitor::check_health()
   auto const& secure_key_types = CryptoManager::get_secure_key_types();
 
   {
-    auto allowed_ciphers = cct->_conf.get_val<std::string>("cephx_allowed_ciphers");
+    auto allowed_ciphers = mon.monmap->auth_allowed_ciphers;
     std::vector<std::string> details;
     for (auto& c : allowed_ciphers) {
       if (!secure_key_types.contains(c)) {
@@ -510,8 +510,7 @@ bool AuthMonitor::check_health()
   }
 
   {
-    auto service_key_type_name = cct->_conf.get_val<std::string>("auth_service_cipher");
-    auto service_key_type = CryptoManager::get_key_type(service_key_type_name);
+    auto service_key_type = mon.monmap->auth_service_cipher;
     if (!secure_key_types.contains(service_key_type)) {
       next.add("AUTH_INSECURE_SERVICE_TICKETS", HEALTH_WARN, "Monitors are configured to issue insecure service key types", 1);
     }
@@ -520,7 +519,7 @@ bool AuthMonitor::check_health()
   std::map<std::string,std::list<std::string>> bad_caps_detail;  // entity -> details
   std::map<EntityName, std::string> bad_key_client_detail;
   std::map<EntityName, std::string> bad_key_service_detail;
-  for (auto const& [entity, auth] : mon.key_server.get_secrets()) {
+  for (auto const& [entity, auth] : mon.get_secrets()) {
     for (auto& p : auth.caps) {
       ostringstream ss;
       if (!valid_caps(p.first, p.second, &ss)) {
@@ -603,7 +602,7 @@ bool AuthMonitor::check_health()
   }
 
   std::vector<std::string> bad_rotating_service_keys;
-  for (auto const& [entity_type, secrets] : mon.key_server.get_rotating_secrets()) {
+  for (auto const& [entity_type, secrets] : mon.get_rotating_secrets()) {
     auto entity_name = EntityName::ceph_entity_type_to_str(entity_type);
     dout(20) << __func__ << ": examining " << entity_name  << " for insecure rotating keys" << dendl;
     if (entity_type == CEPH_ENTITY_TYPE_AUTH) {
@@ -645,7 +644,7 @@ bool AuthMonitor::check_health()
 
 void AuthMonitor::encode_full(MonitorDBStore::TransactionRef t)
 {
-  version_t version = mon.key_server.get_ver();
+  version_t version = mon.get_ver();
   // do not stash full version 0 as it will never be removed nor read
   if (version == 0)
     return;
@@ -654,14 +653,14 @@ void AuthMonitor::encode_full(MonitorDBStore::TransactionRef t)
   ceph_assert(get_last_committed() == version);
 
   bufferlist full_bl;
-  std::scoped_lock l{mon.key_server.get_lock()};
+  std::scoped_lock l{mon.get_lock()};
   dout(20) << __func__ << " key server has "
-           << (mon.key_server.has_secrets() ? "" : "no ")
+           << (mon.has_secrets() ? "" : "no ")
            << "secrets!" << dendl;
   __u8 v = 1;
   encode(v, full_bl);
   encode(max_global_id, full_bl);
-  encode(mon.key_server, full_bl);
+  encode(mon, full_bl);
 
   put_version_full(t, version, full_bl);
   put_version_latest_full(t, version);
@@ -882,7 +881,7 @@ bool AuthMonitor::prep_auth(MonOpRequestRef op, bool paxos_writable)
     else
       type = mon.auth_service_required.pick(supported);
 
-    s->auth_handler = get_auth_service_handler(type, g_ceph_context, &mon.key_server);
+    s->auth_handler = get_auth_service_handler(type, g_ceph_context, &mon);
     if (!s->auth_handler) {
       dout(1) << "client did not provide supported auth type" << dendl;
       ret = -ENOTSUP;
@@ -1054,7 +1053,7 @@ bool AuthMonitor::preprocess_command(MonOpRequestRef op)
     }
   } else if (prefix == "auth get" && !entity_name.empty()) {
     EntityAuth entity_auth;
-    if (!mon.key_server.get_auth(entity, entity_auth)) {
+    if (!mon.get_auth(entity, entity_auth)) {
       ss << "failed to find " << entity_name << " in keyring";
       r = -ENOENT;
     } else {
@@ -1065,7 +1064,7 @@ bool AuthMonitor::preprocess_command(MonOpRequestRef op)
             prefix == "auth print_key" ||
             prefix == "auth get-key") {
     EntityAuth auth;
-    if (!mon.key_server.get_auth(entity, auth)) {
+    if (!mon.get_auth(entity, auth)) {
       ss << "don't have " << entity;
       r = -ENOENT;
       goto done;
@@ -1079,9 +1078,9 @@ bool AuthMonitor::preprocess_command(MonOpRequestRef op)
   } else if (prefix == "auth list" ||
             prefix == "auth ls") {
     if (f) {
-      mon.key_server.encode_formatted("auth", f.get(), rdata);
+      mon.encode_formatted("auth", f.get(), rdata);
     } else {
-      mon.key_server.encode_plaintext(rdata);
+      mon.encode_plaintext(rdata);
     }
     r = 0;
     goto done;
@@ -1100,7 +1099,7 @@ bool AuthMonitor::preprocess_command(MonOpRequestRef op)
 
 void AuthMonitor::export_keyring(KeyRing& keyring)
 {
-  mon.key_server.export_keyring(keyring);
+  mon.export_keyring(keyring);
 }
 
 int AuthMonitor::import_keyring(KeyRing& keyring)
@@ -1123,7 +1122,7 @@ int AuthMonitor::import_keyring(KeyRing& keyring)
 int AuthMonitor::remove_entity(const EntityName &entity)
 {
   dout(10) << __func__ << " " << entity << dendl;
-  if (!mon.key_server.contains(entity))
+  if (!mon.contains(entity))
     return -ENOENT;
 
   KeyServerData::Incremental auth_inc;
@@ -1173,7 +1172,7 @@ int AuthMonitor::exists_and_matches_entity(
 
   EntityAuth existing_auth;
   // does entry already exist?
-  if (mon.key_server.get_auth(name, existing_auth)) {
+  if (mon.get_auth(name, existing_auth)) {
     // key match?
     if (has_secret) {
       if (existing_auth.key.get_secret().cmp(auth.key.get_secret())) {
@@ -1247,8 +1246,8 @@ int AuthMonitor::validate_osd_destroy(
     return -EINVAL;
   }
 
-  if (!mon.key_server.contains(cephx_entity) &&
-      !mon.key_server.contains(lockbox_entity)) {
+  if (!mon.contains(cephx_entity) &&
+      !mon.contains(lockbox_entity)) {
     return -ENOENT;
   }
 
@@ -1428,7 +1427,7 @@ int AuthMonitor::do_osd_new(
   // we must have validated before reaching this point.
   // if keys exist, then this means they also match; otherwise we would
   // have failed before calling this function.
-  bool cephx_exists = mon.key_server.contains(cephx_entity.name);
+  bool cephx_exists = mon.contains(cephx_entity.name);
 
   if (!cephx_exists) {
     int err = add_entity(cephx_entity.name, cephx_entity.auth);
@@ -1436,7 +1435,7 @@ int AuthMonitor::do_osd_new(
   }
 
   if (has_lockbox &&
-      !mon.key_server.contains(lockbox_entity.name)) {
+      !mon.contains(lockbox_entity.name)) {
     int err = add_entity(lockbox_entity.name, lockbox_entity.auth);
     ceph_assert(0 == err);
   }
@@ -1502,9 +1501,22 @@ bool AuthMonitor::valid_caps(const map<string, string>& caps, ostream *out)
 
 int AuthMonitor::get_cipher_type(const cmdmap_t& cmdmap, std::ostream& ss) const
 {
+  static const std::string PREFERRED = "preferred";
   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);
+  std::string cmd_key_string_type;
+  cmd_getval_or<std::string>(cmdmap, "key_type"sv, cmd_key_string_type, PREFERRED);
+  int key_type;
+  if (cmd_key_string_type == PREFERRED) {
+    key_type = mon.monmap->auth_preferred_cipher;
+    key_string_type = fmt::format("`preferred' AKA {}", CryptoManager::get_key_type_name(key_type));
+  } else {
+    key_type = CryptoManager::get_key_type(cmd_key_string_type);
+    if (key_type < 0) {
+      ss << "invalid key type: " << cmd_key_string_type;
+      return -EINVAL;
+    }
+    key_string_type = CryptoManager::get_key_type_name(key_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")) {
@@ -1512,6 +1524,13 @@ int AuthMonitor::get_cipher_type(const cmdmap_t& cmdmap, std::ostream& ss) const
       return -EPERM;
     }
   }
+  auto& allowed_ciphers = mon.monmap->auth_allowed_ciphers;
+  if (auto it = std::find(allowed_ciphers.begin(), allowed_ciphers.end(), key_type); it == allowed_ciphers.end()) {
+    ss << "refusing to create key with type ("
+       << key_string_type
+       << ") that cannot be used for auth (auth_allowed_ciphers)";
+    return -EPERM;
+  }
   return key_type;
 }
 
@@ -1611,6 +1630,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
 
     int key_type = get_cipher_type(cmdmap, ss);
     if (key_type < 0) {
+      err = -EINVAL;
       goto done;
     }
 
@@ -1698,7 +1718,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
     }
 
     EntityAuth entity_auth;
-    if (!mon.key_server.get_auth(entity, entity_auth)) {
+    if (!mon.get_auth(entity, entity_auth)) {
       ss << "entity " << entity << " does not exist";
       err = -ENOENT;
       goto done;
@@ -1706,6 +1726,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
 
     int key_type = get_cipher_type(cmdmap, ss);
     if (key_type < 0) {
+      err = -EINVAL;
       goto done;
     }
 
@@ -1789,12 +1810,13 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
 
     int key_type = get_cipher_type(cmdmap, ss);
     if (key_type < 0) {
+      err = -EINVAL;
       goto done;
     }
 
     // do we have it?
     EntityAuth entity_auth;
-    if (mon.key_server.get_auth(entity, entity_auth)) {
+    if (mon.get_auth(entity, entity_auth)) {
       for (const auto &sys_cap : wanted_caps) {
        if (entity_auth.caps.count(sys_cap.first) == 0 ||
            !entity_auth.caps[sys_cap.first].contents_equal(sys_cap.second)) {
@@ -1870,6 +1892,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
 
     int key_type = get_cipher_type(cmdmap, ss);
     if (key_type < 0) {
+      err = -EINVAL;
       goto done;
     }
 
@@ -1952,7 +1975,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
     }
 
     EntityAuth entity_auth;
-    if (mon.key_server.get_auth(entity, entity_auth)) {
+    if (mon.get_auth(entity, entity_auth)) {
       int rv = _gen_wanted_caps(entity_auth, newcaps, ss);
       ceph_assert(rv == CAPS_UPDATE_REQD or rv == CAPS_UPDATE_NOT_REQD or
                  rv == CAPS_PARSING_ERR);
@@ -1994,7 +2017,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
              !entity_name.empty()) {
     KeyServerData::Incremental auth_inc;
     auth_inc.name = entity;
-    if (!mon.key_server.contains(auth_inc.name)) {
+    if (!mon.contains(auth_inc.name)) {
       err = 0;
       goto done;
     }
@@ -2013,11 +2036,12 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
 
     int key_type = get_cipher_type(cmdmap, ss);
     if (key_type < 0) {
+      err = -EINVAL;
       goto done;
     }
 
     EntityAuth entity_auth;
-    if (!mon.key_server.get_auth(entity, entity_auth)) {
+    if (!mon.get_auth(entity, entity_auth)) {
       ss << "entity does not exist";
       err = -ENOENT;
       goto done;
@@ -2038,7 +2062,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
   } else if (prefix == "auth dump-keys") {
     if (f) {
       f->open_object_section("keys");
-      mon.key_server.dump(f.get());
+      mon.dump(f.get());
       f->close_section();
       f->flush(ds);
       err = 0;
@@ -2060,7 +2084,7 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
 
     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);
+    bool modified = mon.prepare_rotating_update(rot_inc.rotating_bl, true);
     ceph_assert(modified);
     rs = "wiped rotating service keys!";
     dout(5) << __func__ << " wiped rotating service keys!" << dendl;
@@ -2242,14 +2266,14 @@ int AuthMonitor::_update_or_create_entity(const EntityName& entity,
 
   // if entity to be created is already present.
   if (create_entity &&
-      mon.key_server.get_auth(auth_inc.name, auth_inc.auth)) {
+      mon.get_auth(auth_inc.name, auth_inc.auth)) {
     ss << "entity already exists" << auth_inc.name;
     return -EEXIST;
   }
 
   // if entity to be updated is absent.
   if (!create_entity &&
-      !mon.key_server.get_auth(auth_inc.name, auth_inc.auth)) {
+      !mon.get_auth(auth_inc.name, auth_inc.auth)) {
     ss << "couldn't find entry " << auth_inc.name;
     return -ENOENT;
   }
@@ -2321,8 +2345,8 @@ bool AuthMonitor::_upgrade_format_to_dumpling()
 
   bool changed = false;
   map<EntityName, EntityAuth>::iterator p;
-  for (p = mon.key_server.secrets_begin();
-       p != mon.key_server.secrets_end();
+  for (p = mon.secrets_begin();
+       p != mon.secrets_end();
        ++p) {
     // grab mon caps, if any
     string mon_caps;
@@ -2381,8 +2405,8 @@ bool AuthMonitor::_upgrade_format_to_luminous()
 
   bool changed = false;
   map<EntityName, EntityAuth>::iterator p;
-  for (p = mon.key_server.secrets_begin();
-       p != mon.key_server.secrets_end();
+  for (p = mon.secrets_begin();
+       p != mon.secrets_end();
        ++p) {
     string n = p->first.to_str();
 
@@ -2439,7 +2463,7 @@ bool AuthMonitor::_upgrade_format_to_luminous()
   EntityName bootstrap_mgr_name;
   int r = bootstrap_mgr_name.from_str("client.bootstrap-mgr");
   ceph_assert(r);
-  if (!mon.key_server.contains(bootstrap_mgr_name)) {
+  if (!mon.contains(bootstrap_mgr_name)) {
 
     EntityName name = bootstrap_mgr_name;
     EntityAuth auth;
@@ -2461,7 +2485,7 @@ bool AuthMonitor::_upgrade_format_to_mimic()
 
   bool changed = false;
   for (auto &p : auth_lst) {
-    if (mon.key_server.contains(p.first)) {
+    if (mon.contains(p.first)) {
       continue;
     }
     int err = add_entity(p.first, p.second);
@@ -2531,6 +2555,6 @@ void AuthMonitor::dump_info(Formatter *f)
   f->open_object_section("auth");
   f->dump_unsigned("first_committed", get_first_committed());
   f->dump_unsigned("last_committed", get_last_committed());
-  f->dump_unsigned("num_secrets", mon.key_server.get_num_secrets());
+  f->dump_unsigned("num_secrets", mon.get_num_secrets());
   f->close_section();
 }
index 9b6bb4aa86eee925352f4ba561f494883d999cee..fb36f73fdb162a5bcec30c88f1fe95887f8797d8 100644 (file)
@@ -571,6 +571,11 @@ COMMAND("mon set_location " \
        "name=args,type=CephString,n=N,goodchars=[A-Za-z0-9-_.=]",
        "specify location <args> for the monitor <name>, using CRUSH bucket names", \
        "mon", "rw")
+COMMAND("mon set " \
+       "name=name,type=CephString "
+       "name=value,type=CephString",
+       "set mon configuration", \
+       "mon", "rw")
 COMMAND("mon enable_stretch_mode " \
        "name=tiebreaker_mon,type=CephString, "
        "name=new_crush_rule,type=CephString, "
index fda08f59d5452be7365b269560b1570e49ff6d13..ac27063f20a2e2739c3aa6a435e216bcafd201da 100644 (file)
 
 #include "common/Formatter.h"
 
+#include "include/ceph_fs.h"
 #include "include/ceph_features.h"
 #include "include/addr_parsing.h"
+#include "auth/Crypto.h"
 #include "common/ceph_argparse.h"
 #include "common/ceph_json.h"
 #include "common/dns_resolve.h"
@@ -259,6 +261,9 @@ void MonMap::encode(ceph::buffer::list& blist, uint64_t con_features) const
   encode(tiebreaker_mon, blist);
   encode(stretch_marked_down_mons, blist);
   encode(auth_epoch, blist);
+  encode(auth_service_cipher, blist);
+  encode(auth_allowed_ciphers, blist);
+  encode(auth_preferred_cipher, blist);
   ENCODE_FINISH(blist);
 }
 
@@ -325,6 +330,17 @@ void MonMap::decode(ceph::buffer::list::const_iterator& p)
   }
   if (struct_v >= 10) {
     decode(auth_epoch, p);
+    decode(auth_service_cipher, p);
+    decode(auth_allowed_ciphers, p);
+    decode(auth_preferred_cipher, p);
+  } else {
+    /* When decoding an old MonMap, choose defaults reasonable for an existing
+     * cluster:
+     */
+    auth_epoch = 0;
+    auth_service_cipher = CEPH_CRYPTO_AES;
+    auth_allowed_ciphers = {CEPH_CRYPTO_AES, CEPH_CRYPTO_AES256KRB5};
+    auth_preferred_cipher = CEPH_CRYPTO_AES;
   }
   calc_addr_mons();
   DECODE_FINISH(p);
@@ -435,12 +451,44 @@ void MonMap::print(ostream& out) const
     out << "\n";
   }
   out << "auth_epoch " << auth_epoch << "\n";
+  out << "auth_service_cipher " << CryptoManager::get_key_type_name(auth_service_cipher) << "\n";
+  {
+    out << "auth_allowed_ciphers ";
+    bool first = true;
+    for (auto& c : auth_allowed_ciphers) {
+      if (!first) out << ", ";
+      out << CryptoManager::get_key_type_name(c);
+      first = false;
+    }
+    out << "\n";
+  }
+  out << "auth_preferred_cipher " << CryptoManager::get_key_type_name(auth_preferred_cipher) << "\n";
 }
 
 void MonMap::dump(Formatter *f) const
 {
   f->dump_unsigned("epoch", epoch);
   f->dump_unsigned("auth_epoch", auth_epoch);
+
+  f->open_object_section("auth_service_cipher");
+  f->dump_string("name", CryptoManager::get_key_type_name(auth_service_cipher));
+  f->dump_int("value", auth_service_cipher);
+  f->close_section();
+
+  f->open_array_section("auth_allowed_ciphers");
+  for (auto const& k : auth_allowed_ciphers) {
+    f->open_object_section("key_type");
+    f->dump_string("name", CryptoManager::get_key_type_name(k));
+    f->dump_int("value", k);
+    f->close_section();
+  }
+  f->close_section();
+
+  f->open_object_section("auth_preferred_cipher");
+  f->dump_string("name", CryptoManager::get_key_type_name(auth_preferred_cipher));
+  f->dump_int("value", auth_preferred_cipher);
+  f->close_section();
+
   f->dump_stream("fsid") <<  fsid;
   last_changed.gmtime(f->dump_stream("modified"));
   created.gmtime(f->dump_stream("created"));
@@ -889,10 +937,27 @@ seastar::future<> MonMap::build_monmap(const crimson::common::ConfigProxy& conf,
   });
 }
 
+MonMap::MonMap()
+  : auth_service_cipher(CEPH_CRYPTO_NONE)
+  , auth_allowed_ciphers{CEPH_CRYPTO_NONE}
+  , auth_preferred_cipher(CEPH_CRYPTO_NONE)
+{
+}
+
 seastar::future<> MonMap::build_initial(const crimson::common::ConfigProxy& conf, bool for_mkfs)
 {
   /* an invalid epoch so the real monmap doesn't trigger rotation */
   auth_epoch = std::numeric_limits<decltype(auth_epoch)>::max();
+  if (for_mkfs) {
+    auth_service_cipher = CEPH_CRYPTO_AES256KRB5;
+    auth_allowed_ciphers = {CEPH_CRYPTO_AES256KRB5};
+    auth_preferred_cipher = CEPH_CRYPTO_AES256KRB5;
+  } else {
+    /* wait for real monmap */
+    auth_service_cipher = CEPH_CRYPTO_NONE;
+    auth_allowed_ciphers = {CEPH_CRYPTO_NONE};
+    auth_preferred_cipher = CEPH_CRYPTO_NONE;
+  }
 
   // mon_host_override?
   if (maybe_init_with_mon_host(conf.get_val<std::string>("mon_host_override"),
@@ -920,6 +985,13 @@ seastar::future<> MonMap::build_initial(const crimson::common::ConfigProxy& conf
 
 #else  // WITH_CRIMSON
 
+MonMap::MonMap()
+  : auth_service_cipher(CEPH_CRYPTO_NONE)
+  , auth_allowed_ciphers{CEPH_CRYPTO_NONE}
+  , auth_preferred_cipher(CEPH_CRYPTO_NONE)
+{
+}
+
 int MonMap::init_with_monmap(const std::string& monmap, std::ostream& errout)
 {
   int r;
@@ -977,6 +1049,16 @@ int MonMap::build_initial(CephContext *cct, bool for_mkfs, ostream& errout)
 
   /* an invalid epoch so the real monmap doesn't trigger rotation */
   auth_epoch = std::numeric_limits<decltype(auth_epoch)>::max();
+  if (for_mkfs) {
+    auth_service_cipher = CEPH_CRYPTO_AES256KRB5;
+    auth_allowed_ciphers = {CEPH_CRYPTO_AES256KRB5};
+    auth_preferred_cipher = CEPH_CRYPTO_AES256KRB5;
+  } else {
+    /* wait for real monmap */
+    auth_service_cipher = CEPH_CRYPTO_NONE;
+    auth_allowed_ciphers = {CEPH_CRYPTO_NONE};
+    auth_preferred_cipher = CEPH_CRYPTO_NONE;
+  }
 
   // mon_host_override?
   auto mon_host_override = conf.get_val<std::string>("mon_host_override");
index c2ee1fc8425c37d1aae3dd233da85c9c1c0315db..e5e2699de498de35aabc39f88759a4aa0e84fc5f 100644 (file)
@@ -96,7 +96,11 @@ WRITE_CLASS_ENCODER_FEATURES(mon_info_t)
 
 class MonMap {
  public:
-  epoch_t epoch;       // what epoch/version of the monmap
+  epoch_t epoch = 0;       // what epoch/version of the monmap
+  epoch_t auth_epoch = 0;
+  int auth_service_cipher;
+  std::vector<int> auth_allowed_ciphers;
+  int auth_preferred_cipher;
   uuid_d fsid;
   utime_t last_changed;
   utime_t created;
@@ -166,9 +170,6 @@ class MonMap {
   std::string tiebreaker_mon;
   std::set<std::string> stretch_marked_down_mons; // can't be leader or taken proposal in CONNECTIVITY 
                                                   // seriously until fully recovered
-
-  epoch_t auth_epoch = 0;
-
 public:
   void calc_legacy_ranks();
   void calc_addr_mons() {
@@ -181,9 +182,7 @@ public:
     }
   }
 
-  MonMap()
-    : epoch(0) {
-  }
+  MonMap();
 
   uuid_d& get_fsid() { return fsid; }
 
index 654383ee33fa6fc1017049485b217b8a732443a1..75820e7f5a456a7e2c10f7503def79c501795d92 100644 (file)
@@ -164,6 +164,7 @@ MonCommand mon_commands[] = {
 Monitor::Monitor(CephContext* cct_, string nm, MonitorDBStore *s,
                 Messenger *m, Messenger *mgr_m, MonMap *map) :
   Dispatcher(cct_),
+  KeyServer(cct, &keyring),
   AuthServer(cct_),
   name(nm),
   rank(-1), 
@@ -176,7 +177,6 @@ Monitor::Monitor(CephContext* cct_, string nm, MonitorDBStore *s,
   logger(NULL), cluster_logger(NULL), cluster_logger_registered(false),
   monmap(map),
   log_client(cct_, messenger, monmap, LogClient::FLAG_MON),
-  key_server(cct, &keyring),
   auth_cluster_required(cct,
                        cct->_conf->auth_supported.empty() ?
                        cct->_conf->auth_cluster_required : cct->_conf->auth_supported),
@@ -888,7 +888,7 @@ int Monitor::preinit()
         // Attempt to decode and extract keyring only if it is found.
         KeyRing keyring;
         auto p = bl.cbegin();
-        decode(keyring, p);
+        ::decode(keyring, p);
         extract_save_mon_key(keyring);
       }
     }
@@ -900,7 +900,7 @@ int Monitor::preinit()
       EntityName mon_name;
       mon_name.set_type(CEPH_ENTITY_TYPE_MON);
       EntityAuth mon_key;
-      if (key_server.get_auth(mon_name, mon_key)) {
+      if (get_auth(mon_name, mon_key)) {
        dout(1) << "copying mon. key from old db to external keyring" << dendl;
        keyring.add(mon_name, mon_key);
        bufferlist bl;
@@ -1007,7 +1007,7 @@ void Monitor::refresh_from_paxos(bool *need_bootstrap)
   if (r >= 0) {
     try {
       auto p = bl.cbegin();
-      decode(fingerprint, p);
+      ::decode(fingerprint, p);
     }
     catch (ceph::buffer::error& e) {
       dout(10) << __func__ << " failed to decode cluster_fingerprint" << dendl;
@@ -1761,7 +1761,7 @@ void Monitor::handle_sync_get_chunk(MonOpRequestRef op)
     sync_providers.erase(sp.cookie);
   }
 
-  encode(*tx, reply->chunk_bl);
+  ::encode(*tx, reply->chunk_bl);
 
   m->get_connection()->send_message(reply);
 }
@@ -2316,7 +2316,7 @@ void Monitor::win_election(epoch_t epoch, const set<int>& active, uint64_t featu
     // do that anyway for other reasons, though.
     MonitorDBStore::TransactionRef t = paxos->get_pending_transaction();
     bufferlist bl;
-    encode(m, bl);
+    ::encode(m, bl);
     t->put(MONITOR_STORE_PREFIX, "last_metadata", bl);
   }
   elector.process_pending_pings();
@@ -4887,7 +4887,7 @@ void Monitor::handle_ping(MonOpRequestRef op)
   f->close_section();
   stringstream ss;
   f->flush(ss);
-  encode(ss.str(), payload);
+  ::encode(ss.str(), payload);
   reply->set_payload(payload);
   dout(10) << __func__ << " reply payload len " << reply->get_payload().length() << dendl;
   m->get_connection()->send_message(reply);
@@ -5528,7 +5528,7 @@ int Monitor::load_metadata()
   if (r)
     return r;
   auto it = bl.cbegin();
-  decode(mon_metadata, it);
+  ::decode(mon_metadata, it);
 
   pending_metadata = mon_metadata;
   return 0;
@@ -6083,7 +6083,7 @@ void Monitor::prepare_new_fingerprint(MonitorDBStore::TransactionRef t)
   dout(10) << __func__ << " proposing cluster_fingerprint " << nf << dendl;
 
   bufferlist bl;
-  encode(nf, bl);
+  ::encode(nf, bl);
   t->put(MONITOR_NAME, "cluster_fingerprint", bl);
 }
 
@@ -6380,7 +6380,7 @@ bool Monitor::get_authorizer(int service_id, AuthAuthorizer **authorizer)
     CryptoKey key_server_secret;
     CryptoKey keyring_secret;
 
-    bool ksb = key_server.get_secret(name, key_server_secret);
+    bool ksb = get_secret(name, key_server_secret);
     if (ksb) {
       dout(30) << __func__ << ": keyserver found secret=" << key_server_secret << dendl;
     }
@@ -6392,7 +6392,7 @@ bool Monitor::get_authorizer(int service_id, AuthAuthorizer **authorizer)
       dout(0) << " couldn't get secret for mon service from keyring or keyserver"
              << dendl;
       stringstream ss, ds;
-      int err = key_server.list_secrets(ds);
+      int err = list_secrets(ds);
       if (err < 0)
        ss << "no installed auth entries!";
       else
@@ -6414,7 +6414,7 @@ bool Monitor::get_authorizer(int service_id, AuthAuthorizer **authorizer)
       secret = keyring_secret;
     }
 
-    ret = key_server.build_session_auth_info(
+    ret = build_session_auth_info(
       service_id, auth_ticket_info.ticket, secret, (uint64_t)-1, secret.get_type(), info);
     if (ret < 0) {
       dout(0) << __func__ << " failed to build mon session_auth_info "
@@ -6423,7 +6423,7 @@ bool Monitor::get_authorizer(int service_id, AuthAuthorizer **authorizer)
     }
   } else if (service_id == CEPH_ENTITY_TYPE_MGR) {
     // mgr
-    ret = key_server.build_session_auth_info(
+    ret = build_session_auth_info(
       service_id, auth_ticket_info.ticket, std::nullopt, info);
     if (ret < 0) {
       derr << __func__ << " failed to build mgr service session_auth_info "
@@ -6440,11 +6440,11 @@ bool Monitor::get_authorizer(int service_id, AuthAuthorizer **authorizer)
     return false;
   }
   bufferlist ticket_data;
-  encode(blob, ticket_data);
+  ::encode(blob, ticket_data);
 
   auto iter = ticket_data.cbegin();
   CephXTicketHandler handler(g_ceph_context, service_id);
-  decode(handler.ticket, iter);
+  ::decode(handler.ticket, iter);
 
   handler.session_key = info.session_key;
 
@@ -6497,7 +6497,7 @@ int Monitor::handle_auth_request(
     dout(20) << __func__ << ": verify authorizer was_challenge=" << was_challenge << dendl;
     bool isvalid = ah->verify_authorizer(
       cct,
-      use_mon_keyring ? static_cast<KeyStore&>(keyring) : static_cast<KeyStore&>(key_server),
+      use_mon_keyring ? static_cast<KeyStore&>(keyring) : static_cast<KeyStore&>(*this),
       payload,
       auth_meta->get_connection_secret_length(),
       reply,
@@ -6543,7 +6543,7 @@ int Monitor::handle_auth_request(
 
     // handler?
     unique_ptr<AuthServiceHandler> auth_handler{get_auth_service_handler(
-      auth_method, g_ceph_context, &key_server)};
+      auth_method, g_ceph_context, this)};
     if (!auth_handler) {
       dout(1) << __func__ << " auth_method " << auth_method << " not supported"
              << dendl;
@@ -6554,15 +6554,15 @@ int Monitor::handle_auth_request(
     EntityName entity_name;
 
     try {
-      decode(mode, p);
+      ::decode(mode, p);
       if (mode < AUTH_MODE_MON ||
          mode > AUTH_MODE_MON_MAX) {
        dout(1) << __func__ << " invalid mode " << (int)mode << dendl;
        return -EACCES;
       }
       ceph_assert(mode >= AUTH_MODE_MON && mode <= AUTH_MODE_MON_MAX);
-      decode(entity_name, p);
-      decode(con->peer_global_id, p);
+      ::decode(entity_name, p);
+      ::decode(con->peer_global_id, p);
     } catch (ceph::buffer::error& e) {
       dout(1) << __func__ << " failed to decode, " << e.what() << dendl;
       return -EACCES;
@@ -6719,7 +6719,7 @@ bool Monitor::ms_handle_fast_authentication(Connection *con)
     bufferlist::const_iterator p = caps_info.caps.cbegin();
     string str;
     try {
-      decode(str, p);
+      ::decode(str, p);
     } catch (const ceph::buffer::error &err) {
       derr << __func__ << " corrupt cap data for " << con->get_peer_entity_name()
           << " in auth db" << dendl;
@@ -6796,6 +6796,14 @@ void Monitor::notify_new_monmap(bool can_change_external_state, bool remove_rank
     }
   }
   set_elector_disallowed_leaders(can_change_external_state);
+
+  {
+    std::lock_guard lock{cipher_mutex};
+    my_service_cipher = monmap->auth_service_cipher;
+    dout(20) << __func__ << ": my_service_cipher now " << my_service_cipher << dendl;
+    my_allowed_ciphers = monmap->auth_allowed_ciphers;
+    dout(20) << __func__ << ": auth_allowed_ciphers now " << my_allowed_ciphers << dendl;
+  }
 }
 
 void Monitor::set_elector_disallowed_leaders(bool allow_election)
@@ -7123,3 +7131,40 @@ void Monitor::disconnect_disallowed_stretch_sessions()
     session_stretch_allowed(*j, blank);
   }
 }
+
+int Monitor::get_service_cipher() const
+{
+  dout(30) << __func__ << dendl;
+  int cipher;
+  {
+    std::lock_guard lock{cipher_mutex};
+    cipher = my_service_cipher;
+  }
+  dout(30) << __func__ << ": = " << cipher << dendl;
+  return cipher;
+}
+
+bool Monitor::is_cipher_allowed(int cipher) const
+{
+  dout(30) << __func__ << ": " << CryptoManager::get_key_type_name(cipher) << dendl;
+  bool found;
+  {
+    std::lock_guard lock{cipher_mutex};
+    auto it = std::find(my_allowed_ciphers.begin(), my_allowed_ciphers.end(), cipher);
+    found = (it != my_allowed_ciphers.end());
+  }
+  dout(30) << __func__ << ": = " << found << dendl;
+  return found;
+}
+
+std::vector<int> Monitor::get_ciphers_allowed() const
+{
+  dout(30) << __func__ << dendl;
+  std::vector<int> ciphers;
+  {
+    std::lock_guard lock{cipher_mutex};
+    ciphers = my_allowed_ciphers;
+  }
+  dout(30) << __func__ << ": = " << ciphers << dendl;
+  return ciphers;
+}
index 716a05abfd6ed6b83890c2188ba3174602aed17f..47ae8bcae3f8f2e6cf8240c654f3d98dc4cac4b6 100644 (file)
@@ -108,6 +108,7 @@ class AdminSocketHook;
 #define COMPAT_SET_LOC "feature_set"
 
 class Monitor : public Dispatcher,
+               public KeyServer,
                public AuthClient,
                public AuthServer,
                 public md_config_obs_t {
@@ -147,7 +148,6 @@ public:
   LogChannelRef clog;
   LogChannelRef audit_clog;
   KeyRing keyring;
-  KeyServer key_server;
 
   AuthMethodList auth_cluster_required;
   AuthMethodList auth_service_required;
@@ -166,6 +166,15 @@ public:
   uint64_t mgr_proxy_bytes = 0;  // in-flight proxied mgr command message bytes
   std::string gss_ktfile_client{};
 
+private:
+  mutable ceph::mutex cipher_mutex = ceph::make_mutex("Monitor::cipher_mutex");
+  std::vector<int> my_allowed_ciphers;
+  int my_service_cipher = -1;
+public:
+  int get_service_cipher() const override;
+  bool is_cipher_allowed(int cipher) const override;
+  std::vector<int> get_ciphers_allowed() const override;
+
 private:
   void new_tick();
 
index b745a545c62cc50455cf3f96ff5f6793795f0545..ca8ff28cc91734166f30d15782c5828f14995203 100644 (file)
@@ -1250,6 +1250,42 @@ bool MonmapMonitor::prepare_command(MonOpRequestRef op)
     pending_map.stretch_marked_down_mons.clear();
     pending_map.last_changed = ceph_clock_now();
     request_proposal(mon.osdmon());
+  } else if (prefix == "mon set") {
+    std::string name;
+    cmd_getval(cmdmap, "name", name);
+    std::string value;
+    cmd_getval(cmdmap, "value", value);
+    if (name == "auth_service_cipher") {
+      int c = CryptoManager::get_key_type(value);
+      if (c < 0) {
+        err = -EINVAL;
+        goto reply_no_propose;
+      }
+      pending_map.auth_service_cipher = c;
+    } else if (name == "auth_allowed_ciphers") {
+      std::vector<std::string> v;
+      std::vector<int> ciphers;
+      get_str_vec(value, ", ", v);
+      for (auto& cipher : v) {
+        int c = CryptoManager::get_key_type(cipher);
+        if (c < 0) {
+          err = -EINVAL;
+          goto reply_no_propose;
+        }
+        ciphers.push_back(c);
+      }
+      pending_map.auth_allowed_ciphers = std::move(ciphers);
+    } else if (name == "auth_preferred_cipher") {
+      int c = CryptoManager::get_key_type(value);
+      if (c < 0) {
+        err = -EINVAL;
+        goto reply_no_propose;
+      }
+      pending_map.auth_preferred_cipher = c;
+    } else {
+      ss << "unknown name " << name;
+      err = -EINVAL;
+    }
   } else {
     ss << "unknown command " << prefix;
     err = -EINVAL;
index 561ae0a558ff833dc61c0cea33294a0f2693a33f..c33410dbfc9f154b6ce1bdce7796ddc96b713457 100644 (file)
@@ -14640,7 +14640,7 @@ bool OSDMonitor::enforce_pool_op_caps(MonOpRequestRef op)
         pool_name = &osdmap.get_pool_name(m->pool);
       }
 
-      if (!is_unmanaged_snap_op_permitted(cct, mon.key_server,
+      if (!is_unmanaged_snap_op_permitted(cct, mon,
                                           session->entity_name, session->caps,
                                          session->get_peer_socket_addr(),
                                           pool_name)) {
index 3d8f7aa38ae71f1d51e12fbcfccf83550fdfad8b..210700e002dddbfa0f18e4482a32b1de8b228c60 100644 (file)
@@ -177,9 +177,7 @@ int main(int argc, const char **argv)
   EntityName ename(g_conf()->name);
 
   if (key_type < 0) {
-    auto cephx_preferred_cipher = g_conf().get_val<std::string>("cephx_preferred_cipher");
-    cerr << "using key type: " << cephx_preferred_cipher << std::endl;
-    key_type = CryptoManager::get_key_type(cephx_preferred_cipher);
+    key_type = CEPH_CRYPTO_AES256KRB5;
   }
 
   // Enforce the use of gen-key or add-key when creating to avoid ending up
index b09ddf16bbd4af5e5f993c4c3d321248e1638c7d..f98e738c9be1682fbd35bd5410f88181385b3480 100644 (file)
@@ -353,6 +353,9 @@ int main(int argc, const char **argv)
     monmap.epoch = 0;
     monmap.created = ceph_clock_now();
     monmap.last_changed = monmap.created;
+    monmap.auth_service_cipher = CEPH_CRYPTO_AES256KRB5;
+    monmap.auth_allowed_ciphers = {CEPH_CRYPTO_AES256KRB5};
+    monmap.auth_preferred_cipher = CEPH_CRYPTO_AES256KRB5;
     srand(getpid() + time(0));
     if (g_conf().get_val<uuid_d>("fsid").is_zero()) {
       monmap.generate_fsid();