]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr: validate that profile caps are actually valid
authorJason Dillaman <dillaman@redhat.com>
Thu, 17 Oct 2019 13:37:13 +0000 (09:37 -0400)
committerJason Dillaman <dillaman@redhat.com>
Tue, 29 Oct 2019 12:35:03 +0000 (08:35 -0400)
Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/mgr/MgrCap.cc
src/mgr/MgrCap.h
src/test/mgr/test_mgrcap.cc

index ed5ed46d62c2e58a133b8fb222081c3e62f6d615..5c990a1bdf611a04d2badfdd6fe1cbc08c127185 100644 (file)
@@ -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<std::string, std::string>& 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;
   }
index dc14ac2d2a910233d4ea9bd9ed1c0dff71fd4bf4..3482ff21eed1f9c8589dda9718afc4c151c2eb4c 100644 (file)
@@ -104,7 +104,7 @@ struct MgrCapGrant {
   // needed by expand_profile() (via is_match()) and cached here.
   mutable std::list<MgrCapGrant> profile_grants;
 
-  void expand_profile() const;
+  void expand_profile(std::ostream *err=nullptr) const;
 
   MgrCapGrant() : allow(0) {}
   MgrCapGrant(std::string&& service,
index 3c79d87906e9d08a7ac3b3d5bd15900827e6affb..3fddb69d0728d3ff97b5abed42f0683e93ac30e7 100644 (file)
@@ -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, {}));