From: Sage Weil Date: Tue, 7 Mar 2017 21:28:24 +0000 (-0500) Subject: mon/MonCap: pass entity type (mgr, mon) to is_capable X-Git-Tag: v12.0.2~252^2~37 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=20114e0e8278ddc3dc5544a529198fa8ec107ac1;p=ceph.git mon/MonCap: pass entity type (mgr, mon) to is_capable This lets us define different meanings for profiles on the mon and mgr. Signed-off-by: Sage Weil --- diff --git a/src/mgr/DaemonServer.cc b/src/mgr/DaemonServer.cc index b154b8eee2bf..b6e2bc6079b5 100644 --- a/src/mgr/DaemonServer.cc +++ b/src/mgr/DaemonServer.cc @@ -351,11 +351,15 @@ bool DaemonServer::_allowed_command( bool cmd_w = this_cmd->requires_perm('w'); bool cmd_x = this_cmd->requires_perm('x'); - bool capable = s->caps.is_capable(g_ceph_context, s->entity_name, - module, prefix, param_str_map, - cmd_r, cmd_w, cmd_x); - - dout(10) << " " << (capable ? "" : "not ") << "capable" << dendl; + bool capable = s->caps.is_capable( + g_ceph_context, + CEPH_ENTITY_TYPE_MGR, + s->entity_name, + module, prefix, param_str_map, + cmd_r, cmd_w, cmd_x); + + dout(10) << " " << s->entity_name << " " + << (capable ? "" : "not ") << "capable" << dendl; return capable; } diff --git a/src/mon/MonCap.cc b/src/mon/MonCap.cc index 972d51651fa6..7f3582976b5c 100644 --- a/src/mon/MonCap.cc +++ b/src/mon/MonCap.cc @@ -113,12 +113,42 @@ BOOST_FUSION_ADAPT_STRUCT(StringConstraint, // -void MonCapGrant::expand_profile(EntityName name) const +void MonCapGrant::expand_profile(int daemon_type, const EntityName& name) const { // only generate this list once if (!profile_grants.empty()) return; + if (profile == "read-only") { + // grants READ-ONLY caps monitor-wide + // 'auth' requires MON_CAP_X even for RO, which we do not grant here. + profile_grants.push_back(mon_rwxa_t(MON_CAP_R)); + return; + } + + if (profile == "read-write") { + // grants READ-WRITE caps monitor-wide + // 'auth' requires MON_CAP_X for all operations, which we do not grant. + profile_grants.push_back(mon_rwxa_t(MON_CAP_R | MON_CAP_W)); + return; + } + + switch (daemon_type) { + case CEPH_ENTITY_TYPE_MON: + expand_profile_mon(name); + return; + case CEPH_ENTITY_TYPE_MGR: + expand_profile_mgr(name); + return; + } +} + +void MonCapGrant::expand_profile_mgr(const EntityName& name) const +{ +} + +void MonCapGrant::expand_profile_mon(const EntityName& name) const +{ if (profile == "mon") { profile_grants.push_back(MonCapGrant("mon", MON_CAP_ALL)); profile_grants.push_back(MonCapGrant("log", MON_CAP_ALL)); @@ -209,18 +239,6 @@ void MonCapGrant::expand_profile(EntityName name) const profile_grants.push_back(MonCapGrant("pg", MON_CAP_R)); } - if (profile == "read-only") { - // grants READ-ONLY caps monitor-wide - // 'auth' requires MON_CAP_X even for RO, which we do not grant here. - profile_grants.push_back(mon_rwxa_t(MON_CAP_R)); - } - - if (profile == "read-write") { - // grants READ-WRITE caps monitor-wide - // 'auth' requires MON_CAP_X for all operations, which we do not grant. - profile_grants.push_back(mon_rwxa_t(MON_CAP_R | MON_CAP_W)); - } - if (profile == "role-definer") { // grants ALL caps to the auth subsystem, read-only on the // monitor subsystem and nothing else. @@ -230,16 +248,17 @@ void MonCapGrant::expand_profile(EntityName name) const } mon_rwxa_t MonCapGrant::get_allowed(CephContext *cct, + int daemon_type, EntityName name, const std::string& s, const std::string& c, const map& c_args) const { if (profile.length()) { - expand_profile(name); + expand_profile(daemon_type, name); mon_rwxa_t a; for (list::const_iterator p = profile_grants.begin(); p != profile_grants.end(); ++p) - a = a | p->get_allowed(cct, name, s, c, c_args); + a = a | p->get_allowed(cct, daemon_type, name, s, c, c_args); return a; } if (service.length()) { @@ -296,6 +315,7 @@ void MonCap::set_allow_all() } bool MonCap::is_capable(CephContext *cct, + int daemon_type, EntityName name, const string& service, const string& command, const map& command_args, @@ -321,7 +341,8 @@ bool MonCap::is_capable(CephContext *cct, } // check enumerated caps - allow = allow | p->get_allowed(cct, name, service, command, command_args); + allow = allow | p->get_allowed(cct, daemon_type, name, service, command, + command_args); if ((!op_may_read || (allow & MON_CAP_R)) && (!op_may_write || (allow & MON_CAP_W)) && (!op_may_exec || (allow & MON_CAP_X))) { diff --git a/src/mon/MonCap.h b/src/mon/MonCap.h index 3bdd5479838b..25684d307624 100644 --- a/src/mon/MonCap.h +++ b/src/mon/MonCap.h @@ -78,7 +78,9 @@ struct MonCapGrant { // needed by expand_profile() (via is_match()) and cached here. mutable list profile_grants; - void expand_profile(EntityName name) const; + void expand_profile(int daemon_type, const EntityName& name) const; + void expand_profile_mon(const EntityName& name) const; + void expand_profile_mgr(const EntityName& name) const; MonCapGrant() : allow(0) {} // cppcheck-suppress noExplicitConstructor @@ -101,6 +103,7 @@ struct MonCapGrant { * @return bits we allow */ mon_rwxa_t get_allowed(CephContext *cct, + int daemon_type, ///< CEPH_ENTITY_TYPE_* EntityName name, const std::string& service, const std::string& command, @@ -138,6 +141,7 @@ struct MonCap { * This method actually checks a description of a particular operation against * what the capability has specified. * + * @param daemon_type CEPH_ENTITY_TYPE_* for the service (MON or MGR) * @param service service name * @param command command id * @param command_args @@ -147,6 +151,7 @@ struct MonCap { * @return true if the operation is allowed, false otherwise */ bool is_capable(CephContext *cct, + int daemon_type, EntityName name, const string& service, const string& command, const map& command_args, diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index 46a7ed55f293..bf2410e59525 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -2683,9 +2683,12 @@ bool Monitor::_allowed_command(MonSession *s, string &module, string &prefix, bool cmd_w = this_cmd->requires_perm('w'); bool cmd_x = this_cmd->requires_perm('x'); - bool capable = s->caps.is_capable(g_ceph_context, s->entity_name, - module, prefix, param_str_map, - cmd_r, cmd_w, cmd_x); + bool capable = s->caps.is_capable( + g_ceph_context, + CEPH_ENTITY_TYPE_MON, + s->entity_name, + module, prefix, param_str_map, + cmd_r, cmd_w, cmd_x); dout(10) << __func__ << " " << (capable ? "" : "not ") << "capable" << dendl; return capable; diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index c6453f3478b7..3147d6066ad5 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -2674,7 +2674,10 @@ bool OSDMonitor::preprocess_remove_snaps(MonOpRequestRef op) MonSession *session = m->get_session(); if (!session) goto ignore; - if (!session->caps.is_capable(g_ceph_context, session->entity_name, + if (!session->caps.is_capable( + g_ceph_context, + CEPH_ENTITY_TYPE_MON, + session->entity_name, "osd", "osd pool rmsnap", {}, true, true, false)) { dout(0) << "got preprocess_remove_snaps from entity with insufficient caps " << session->caps << dendl; diff --git a/src/mon/Session.h b/src/mon/Session.h index 0f253fce3b5c..75051bf6312f 100644 --- a/src/mon/Session.h +++ b/src/mon/Session.h @@ -78,10 +78,12 @@ struct MonSession : public RefCountedObject { bool is_capable(string service, int mask) { map args; - return caps.is_capable(g_ceph_context, - entity_name, - service, "", args, - mask & MON_CAP_R, mask & MON_CAP_W, mask & MON_CAP_X); + return caps.is_capable( + g_ceph_context, + CEPH_ENTITY_TYPE_MON, + entity_name, + service, "", args, + mask & MON_CAP_R, mask & MON_CAP_W, mask & MON_CAP_X); } }; diff --git a/src/test/mon/moncap.cc b/src/test/mon/moncap.cc index f9a0b5c06e78..8b55719fe16e 100644 --- a/src/test/mon/moncap.cc +++ b/src/test/mon/moncap.cc @@ -177,7 +177,7 @@ TEST(MonCap, AllowAll) { ASSERT_TRUE(cap.parse("allow *", NULL)); ASSERT_TRUE(cap.is_allow_all()); - ASSERT_TRUE(cap.is_capable(NULL, EntityName(), + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, EntityName(), "foo", "asdf", map(), true, true, true)); MonCap cap2; @@ -195,29 +195,46 @@ TEST(MonCap, ProfileOSD) { name.from_str("osd.123"); map ca; - ASSERT_TRUE(cap.is_capable(NULL, name, "osd", "", ca, true, false, false)); - ASSERT_TRUE(cap.is_capable(NULL, name, "osd", "", ca, true, true, false)); - ASSERT_TRUE(cap.is_capable(NULL, name, "osd", "", ca, true, true, true)); - ASSERT_TRUE(cap.is_capable(NULL, name, "osd", "", ca, true, true, true)); - ASSERT_TRUE(cap.is_capable(NULL, name, "mon", "", ca, true, false,false)); - - ASSERT_FALSE(cap.is_capable(NULL, name, "mds", "", ca, true, true, true)); - ASSERT_FALSE(cap.is_capable(NULL, name, "mon", "", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "osd", "", ca, true, false, false)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "osd", "", ca, true, true, false)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "osd", "", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "osd", "", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "mon", "", ca, true, false,false)); + + ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "mds", "", ca, true, true, true)); + ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "mon", "", ca, true, true, true)); ca.clear(); - ASSERT_FALSE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true, true)); + ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key get", ca, true, true, true)); ca["key"] = "daemon-private/osd.123"; - ASSERT_FALSE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true, true)); + ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key get", ca, true, true, true)); ca["key"] = "daemon-private/osd.12/asdf"; - ASSERT_FALSE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true, true)); + ASSERT_FALSE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key get", ca, true, true, true)); ca["key"] = "daemon-private/osd.123/"; - ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true, true)); - ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true, true)); - ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key get", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key get", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key get", ca, true, true, true)); ca["key"] = "daemon-private/osd.123/foo"; - ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key get", ca, true, true, true)); - ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key put", ca, true, true, true)); - ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key exists", ca, true, true, true)); - ASSERT_TRUE(cap.is_capable(NULL, name, "", "config-key delete", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key get", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key put", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key exists", ca, true, true, true)); + ASSERT_TRUE(cap.is_capable(NULL, CEPH_ENTITY_TYPE_MON, + name, "", "config-key delete", ca, true, true, true)); }