From 9193d8762347af65bebdaea673175113f7ccd01a Mon Sep 17 00:00:00 2001 From: Jason Dillaman Date: Thu, 17 Oct 2019 09:37:13 -0400 Subject: [PATCH] mgr: validate that profile caps are actually valid Signed-off-by: Jason Dillaman --- src/mgr/MgrCap.cc | 28 ++++++++++++++++++++++++++-- src/mgr/MgrCap.h | 2 +- src/test/mgr/test_mgrcap.cc | 23 ++++++++++++----------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/mgr/MgrCap.cc b/src/mgr/MgrCap.cc index ed5ed46d62c..5c990a1bdf6 100644 --- a/src/mgr/MgrCap.cc +++ b/src/mgr/MgrCap.cc @@ -131,7 +131,7 @@ void MgrCapGrant::parse_network() { &network_prefix); } -void MgrCapGrant::expand_profile() const { +void MgrCapGrant::expand_profile(std::ostream *err) const { // only generate this list once if (!profile_grants.empty()) { return; @@ -160,6 +160,12 @@ void MgrCapGrant::expand_profile() const { for (auto& [key, constraint] : arguments) { if (key == "pool" || key == "namespace") { filtered_arguments[key] = std::move(constraint); + } else { + if (err != nullptr) { + *err << "profile '" << profile << "' does not recognize key '" << key + << "'"; + } + return; } } @@ -174,6 +180,10 @@ void MgrCapGrant::expand_profile() const { std::move(filtered_arguments), perms}); return; } + + if (err != nullptr) { + *err << "unrecognized profile '" << profile << "'"; + } } bool MgrCapGrant::validate_arguments( @@ -218,7 +228,7 @@ mgr_rwxa_t MgrCapGrant::get_allowed( const std::string& m, const std::string& c, const std::map& args) const { if (!profile.empty()) { - expand_profile(); + expand_profile(nullptr); mgr_rwxa_t a; for (auto& grant : profile_grants) { a = a | grant.get_allowed(cct, name, s, m, c, args); @@ -523,8 +533,22 @@ bool MgrCap::parse(const std::string& str, ostream *err) { bool r = qi::parse(iter, end, exp, *this); if (r && iter == end) { text = str; + + std::stringstream profile_err; for (auto& g : grants) { g.parse_network(); + + if (!g.profile.empty()) { + g.expand_profile(&profile_err); + } + } + + if (!profile_err.str().empty()) { + if (err != nullptr) { + *err << "mgr capability parse failed during profile evaluation: " + << profile_err.str(); + } + return false; } return true; } diff --git a/src/mgr/MgrCap.h b/src/mgr/MgrCap.h index dc14ac2d2a9..3482ff21eed 100644 --- a/src/mgr/MgrCap.h +++ b/src/mgr/MgrCap.h @@ -104,7 +104,7 @@ struct MgrCapGrant { // needed by expand_profile() (via is_match()) and cached here. mutable std::list profile_grants; - void expand_profile() const; + void expand_profile(std::ostream *err=nullptr) const; MgrCapGrant() : allow(0) {} MgrCapGrant(std::string&& service, diff --git a/src/test/mgr/test_mgrcap.cc b/src/test/mgr/test_mgrcap.cc index 3c79d87906e..3fddb69d072 100644 --- a/src/test/mgr/test_mgrcap.cc +++ b/src/test/mgr/test_mgrcap.cc @@ -33,9 +33,9 @@ const char *parse_good[] = { "\tallow\nrwx\t", "allow service=foo x", "allow service=\"froo\" x", - "allow profile osd", - "allow profile osd-bootstrap", - "allow profile \"mds-bootstrap\", allow *", + "allow profile read-only", + "allow profile read-write", + "allow profile \"rbd-read-only\", allow *", "allow command \"a b c\"", "allow command abc", "allow command abc with arg=foo", @@ -63,16 +63,16 @@ const char *parse_good[] = { "allow command \"foo bar\" with arg=\"baz\"", "allow command \"foo bar\" with arg=\"baz.xx\"", "allow command \"foo bar\" with arg = \"baz.xx\"", - "profile osd", + "profile crash", "profile rbd pool=ABC namespace=NS", - "profile \"mds-bootstrap\", profile foo", + "profile \"rbd-read-only\", profile crash", "allow * network 1.2.3.4/24", "allow * network ::1/128", "allow * network [aa:bb::1]/128", "allow service=foo x network 1.2.3.4/16", "allow command abc network 1.2.3.4/8", - "profile osd network 1.2.3.4/32", - "allow profile mon network 1.2.3.4/32", + "profile crash network 1.2.3.4/32", + "allow profile crash network 1.2.3.4/32", 0 }; @@ -93,10 +93,8 @@ const char *parse_identity[] = { "allow r", "allow rwx", "allow service foo x", - "profile osd", - "profile osd-bootstrap", - "profile mds-bootstrap, allow *", - "profile \"foo bar\", allow *", + "profile crash", + "profile rbd-read-only, allow *", "profile rbd namespace=NS pool=ABC", "allow command abc", "allow command \"a b c\"", @@ -267,6 +265,9 @@ TEST(MgrCap, Profile) { MgrCap cap; ASSERT_FALSE(cap.is_allow_all()); + ASSERT_FALSE(cap.parse("profile unknown")); + ASSERT_FALSE(cap.parse("profile rbd invalid-key=value")); + ASSERT_TRUE(cap.parse("profile rbd", nullptr)); ASSERT_FALSE(cap.is_capable(nullptr, {}, "", "abc", "", {}, true, false, false, {})); -- 2.39.5