summaryrefslogtreecommitdiffstats
path: root/src/auth/AuthRegistry.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/auth/AuthRegistry.cc')
-rw-r--r--src/auth/AuthRegistry.cc373
1 files changed, 373 insertions, 0 deletions
diff --git a/src/auth/AuthRegistry.cc b/src/auth/AuthRegistry.cc
new file mode 100644
index 000000000..0043567fb
--- /dev/null
+++ b/src/auth/AuthRegistry.cc
@@ -0,0 +1,373 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "AuthRegistry.h"
+
+#include "cephx/CephxAuthorizeHandler.h"
+#ifdef HAVE_GSSAPI
+#include "krb/KrbAuthorizeHandler.hpp"
+#endif
+#include "none/AuthNoneAuthorizeHandler.h"
+#include "common/ceph_context.h"
+#include "common/debug.h"
+#include "auth/KeyRing.h"
+
+#define dout_subsys ceph_subsys_auth
+#undef dout_prefix
+#define dout_prefix *_dout << "AuthRegistry(" << this << ") "
+
+using std::string;
+
+AuthRegistry::AuthRegistry(CephContext *cct)
+ : cct(cct)
+{
+ cct->_conf.add_observer(this);
+}
+
+AuthRegistry::~AuthRegistry()
+{
+ cct->_conf.remove_observer(this);
+ for (auto i : authorize_handlers) {
+ delete i.second;
+ }
+}
+
+const char** AuthRegistry::get_tracked_conf_keys() const
+{
+ static const char *keys[] = {
+ "auth_supported",
+ "auth_client_required",
+ "auth_cluster_required",
+ "auth_service_required",
+ "ms_mon_cluster_mode",
+ "ms_mon_service_mode",
+ "ms_mon_client_mode",
+ "ms_cluster_mode",
+ "ms_service_mode",
+ "ms_client_mode",
+ "keyring",
+ NULL
+ };
+ return keys;
+}
+
+void AuthRegistry::handle_conf_change(
+ const ConfigProxy& conf,
+ const std::set<std::string>& changed)
+{
+ std::scoped_lock l(lock);
+ _refresh_config();
+}
+
+
+void AuthRegistry::_parse_method_list(const string& s,
+ std::vector<uint32_t> *v)
+{
+ std::list<std::string> sup_list;
+ get_str_list(s, sup_list);
+ if (sup_list.empty()) {
+ lderr(cct) << "WARNING: empty auth protocol list" << dendl;
+ }
+ v->clear();
+ for (auto& i : sup_list) {
+ ldout(cct, 5) << "adding auth protocol: " << i << dendl;
+ if (i == "cephx") {
+ v->push_back(CEPH_AUTH_CEPHX);
+ } else if (i == "none") {
+ v->push_back(CEPH_AUTH_NONE);
+ } else if (i == "gss") {
+ v->push_back(CEPH_AUTH_GSS);
+ } else {
+ lderr(cct) << "WARNING: unknown auth protocol defined: " << i << dendl;
+ }
+ }
+ if (v->empty()) {
+ lderr(cct) << "WARNING: no auth protocol defined" << dendl;
+ }
+ ldout(cct,20) << __func__ << " " << s << " -> " << *v << dendl;
+}
+
+void AuthRegistry::_parse_mode_list(const string& s,
+ std::vector<uint32_t> *v)
+{
+ std::list<std::string> sup_list;
+ get_str_list(s, sup_list);
+ if (sup_list.empty()) {
+ lderr(cct) << "WARNING: empty auth protocol list" << dendl;
+ }
+ v->clear();
+ for (auto& i : sup_list) {
+ ldout(cct, 5) << "adding con mode: " << i << dendl;
+ if (i == "crc") {
+ v->push_back(CEPH_CON_MODE_CRC);
+ } else if (i == "secure") {
+ v->push_back(CEPH_CON_MODE_SECURE);
+ } else {
+ lderr(cct) << "WARNING: unknown connection mode " << i << dendl;
+ }
+ }
+ if (v->empty()) {
+ lderr(cct) << "WARNING: no connection modes defined" << dendl;
+ }
+ ldout(cct,20) << __func__ << " " << s << " -> " << *v << dendl;
+}
+
+void AuthRegistry::_refresh_config()
+{
+ if (cct->_conf->auth_supported.size()) {
+ _parse_method_list(cct->_conf->auth_supported, &cluster_methods);
+ _parse_method_list(cct->_conf->auth_supported, &service_methods);
+ _parse_method_list(cct->_conf->auth_supported, &client_methods);
+ } else {
+ _parse_method_list(cct->_conf->auth_cluster_required, &cluster_methods);
+ _parse_method_list(cct->_conf->auth_service_required, &service_methods);
+ _parse_method_list(cct->_conf->auth_client_required, &client_methods);
+ }
+ _parse_mode_list(cct->_conf.get_val<string>("ms_mon_cluster_mode"),
+ &mon_cluster_modes);
+ _parse_mode_list(cct->_conf.get_val<string>("ms_mon_service_mode"),
+ &mon_service_modes);
+ _parse_mode_list(cct->_conf.get_val<string>("ms_mon_client_mode"),
+ &mon_client_modes);
+ _parse_mode_list(cct->_conf.get_val<string>("ms_cluster_mode"),
+ &cluster_modes);
+ _parse_mode_list(cct->_conf.get_val<string>("ms_service_mode"),
+ &service_modes);
+ _parse_mode_list(cct->_conf.get_val<string>("ms_client_mode"),
+ &client_modes);
+
+ ldout(cct,10) << __func__ << " cluster_methods " << cluster_methods
+ << " service_methods " << service_methods
+ << " client_methods " << client_methods
+ << dendl;
+ ldout(cct,10) << __func__ << " mon_cluster_modes " << mon_cluster_modes
+ << " mon_service_modes " << mon_service_modes
+ << " mon_client_modes " << mon_client_modes
+ << "; cluster_modes " << cluster_modes
+ << " service_modes " << service_modes
+ << " client_modes " << client_modes
+ << dendl;
+
+ // if we have no keyring, filter out cephx
+ _no_keyring_disabled_cephx = false;
+ bool any_cephx = false;
+ for (auto *p : {&cluster_methods, &service_methods, &client_methods}) {
+ auto q = std::find(p->begin(), p->end(), CEPH_AUTH_CEPHX);
+ if (q != p->end()) {
+ any_cephx = true;
+ break;
+ }
+ }
+ if (any_cephx) {
+ KeyRing k;
+ int r = k.from_ceph_context(cct);
+ if (r == -ENOENT) {
+ for (auto *p : {&cluster_methods, &service_methods, &client_methods}) {
+ auto q = std::find(p->begin(), p->end(), CEPH_AUTH_CEPHX);
+ if (q != p->end()) {
+ p->erase(q);
+ _no_keyring_disabled_cephx = true;
+ }
+ }
+ }
+ if (_no_keyring_disabled_cephx) {
+ lderr(cct) << "no keyring found at " << cct->_conf->keyring
+ << ", disabling cephx" << dendl;
+ }
+ }
+}
+
+void AuthRegistry::get_supported_methods(
+ int peer_type,
+ std::vector<uint32_t> *methods,
+ std::vector<uint32_t> *modes) const
+{
+ if (methods) {
+ methods->clear();
+ }
+ if (modes) {
+ modes->clear();
+ }
+ std::scoped_lock l(lock);
+ switch (cct->get_module_type()) {
+ case CEPH_ENTITY_TYPE_CLIENT:
+ // i am client
+ if (methods) {
+ *methods = client_methods;
+ }
+ if (modes) {
+ switch (peer_type) {
+ case CEPH_ENTITY_TYPE_MON:
+ case CEPH_ENTITY_TYPE_MGR:
+ *modes = mon_client_modes;
+ break;
+ default:
+ *modes = client_modes;
+ }
+ }
+ return;
+ case CEPH_ENTITY_TYPE_MON:
+ case CEPH_ENTITY_TYPE_MGR:
+ // i am mon/mgr
+ switch (peer_type) {
+ case CEPH_ENTITY_TYPE_MON:
+ case CEPH_ENTITY_TYPE_MGR:
+ // they are mon/mgr
+ if (methods) {
+ *methods = cluster_methods;
+ }
+ if (modes) {
+ *modes = mon_cluster_modes;
+ }
+ break;
+ default:
+ // they are anything but mons
+ if (methods) {
+ *methods = service_methods;
+ }
+ if (modes) {
+ *modes = mon_service_modes;
+ }
+ }
+ return;
+ default:
+ // i am a non-mon daemon
+ switch (peer_type) {
+ case CEPH_ENTITY_TYPE_MON:
+ case CEPH_ENTITY_TYPE_MGR:
+ // they are a mon daemon
+ if (methods) {
+ *methods = cluster_methods;
+ }
+ if (modes) {
+ *modes = mon_cluster_modes;
+ }
+ break;
+ case CEPH_ENTITY_TYPE_MDS:
+ case CEPH_ENTITY_TYPE_OSD:
+ // they are another daemon
+ if (methods) {
+ *methods = cluster_methods;
+ }
+ if (modes) {
+ *modes = cluster_modes;
+ }
+ break;
+ default:
+ // they are a client
+ if (methods) {
+ *methods = service_methods;
+ }
+ if (modes) {
+ *modes = service_modes;
+ }
+ break;
+ }
+ }
+}
+
+bool AuthRegistry::is_supported_method(int peer_type, int method) const
+{
+ std::vector<uint32_t> s;
+ get_supported_methods(peer_type, &s);
+ return std::find(s.begin(), s.end(), method) != s.end();
+}
+
+bool AuthRegistry::any_supported_methods(int peer_type) const
+{
+ std::vector<uint32_t> s;
+ get_supported_methods(peer_type, &s);
+ return !s.empty();
+}
+
+void AuthRegistry::get_supported_modes(
+ int peer_type,
+ uint32_t auth_method,
+ std::vector<uint32_t> *modes) const
+{
+ std::vector<uint32_t> s;
+ get_supported_methods(peer_type, nullptr, &s);
+ if (auth_method == CEPH_AUTH_NONE) {
+ // filter out all but crc for AUTH_NONE
+ modes->clear();
+ for (auto mode : s) {
+ if (mode == CEPH_CON_MODE_CRC) {
+ modes->push_back(mode);
+ }
+ }
+ } else {
+ *modes = s;
+ }
+}
+
+uint32_t AuthRegistry::pick_mode(
+ int peer_type,
+ uint32_t auth_method,
+ const std::vector<uint32_t>& preferred_modes)
+{
+ std::vector<uint32_t> allowed_modes;
+ get_supported_modes(peer_type, auth_method, &allowed_modes);
+ for (auto mode : preferred_modes) {
+ if (std::find(allowed_modes.begin(), allowed_modes.end(), mode)
+ != allowed_modes.end()) {
+ return mode;
+ }
+ }
+ ldout(cct,1) << "failed to pick con mode from client's " << preferred_modes
+ << " and our " << allowed_modes << dendl;
+ return CEPH_CON_MODE_UNKNOWN;
+}
+
+AuthAuthorizeHandler *AuthRegistry::get_handler(int peer_type, int method)
+{
+ std::scoped_lock l{lock};
+ ldout(cct,20) << __func__ << " peer_type " << peer_type << " method " << method
+ << " cluster_methods " << cluster_methods
+ << " service_methods " << service_methods
+ << " client_methods " << client_methods
+ << dendl;
+ if (cct->get_module_type() == CEPH_ENTITY_TYPE_CLIENT) {
+ return nullptr;
+ }
+ switch (peer_type) {
+ case CEPH_ENTITY_TYPE_MON:
+ case CEPH_ENTITY_TYPE_MGR:
+ case CEPH_ENTITY_TYPE_MDS:
+ case CEPH_ENTITY_TYPE_OSD:
+ if (std::find(cluster_methods.begin(), cluster_methods.end(), method) ==
+ cluster_methods.end()) {
+ return nullptr;
+ }
+ break;
+ default:
+ if (std::find(service_methods.begin(), service_methods.end(), method) ==
+ service_methods.end()) {
+ return nullptr;
+ }
+ break;
+ }
+
+ auto iter = authorize_handlers.find(method);
+ if (iter != authorize_handlers.end()) {
+ return iter->second;
+ }
+ AuthAuthorizeHandler *ah = nullptr;
+ switch (method) {
+ case CEPH_AUTH_NONE:
+ ah = new AuthNoneAuthorizeHandler();
+ break;
+ case CEPH_AUTH_CEPHX:
+ ah = new CephxAuthorizeHandler();
+ break;
+#ifdef HAVE_GSSAPI
+ case CEPH_AUTH_GSS:
+ ah = new KrbAuthorizeHandler();
+ break;
+#endif
+ }
+ if (ah) {
+ authorize_handlers[method] = ah;
+ }
+ return ah;
+}
+