]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
OSD/OSDCap: Allow namespace and pool tag to be combined
authorDouglas Fuller <dfuller@redhat.com>
Mon, 9 Oct 2017 19:20:47 +0000 (15:20 -0400)
committerDouglas Fuller <dfuller@redhat.com>
Tue, 7 Nov 2017 15:29:39 +0000 (10:29 -0500)
Extend the OSD auth caps grammar to allow namespace and pool tag
cap combinations. Namespace must be listed first. Example:

allow rwx namespace ns* tag application key = value

Signed-off-by: Douglas Fuller <dfuller@redhat.com>
doc/man/8/ceph-authtool.rst
src/osd/OSDCap.cc
src/osd/OSDCap.h
src/test/osd/osdcap.cc

index a3e719e29b002dcc04c289ddf1257d2db5f09e35..56a0639cc8ba224068410c1d114b78b2e9ed0aae 100644 (file)
@@ -139,9 +139,9 @@ In general, an osd capability follows the grammar::
 
         osdcap  := grant[,grant...]
         grant   := allow (match capspec | capspec match)
-        match   := [pool[=]<poolname> | object_prefix <prefix>
-                    | tag <application-name> <key>=<value> 
-                    | namespace[=]<rados-namespace> ]
+        match   := [ pool[=]<poolname> | object_prefix <prefix>
+                    | namespace[=]<rados-namespace>
+                    | tag <application-name> <key>=<value> ]
         capspec := * | [r][w][x] [class-read] [class-write]
 
 The capspec determines what kind of operations the entity can perform::
index e0d028d17704257bb26146c5e22d4a481f201cb2..95c94ebfef8f69fcf6538e2a3e1fabe0548d71a0 100644 (file)
@@ -82,9 +82,13 @@ ostream& operator<<(ostream& out, const OSDCapMatch& m)
 {
   if (m.auid != -1LL) {
     out << "auid " << m.auid << " ";
-  } else if (!m.pool_namespace.pool_name.empty() || m.pool_namespace.nspace) {
+  }
+
+  if (!m.pool_namespace.pool_name.empty() || m.pool_namespace.nspace) {
     out << m.pool_namespace;
-  } else if (!m.pool_tag.application.empty()) {
+  }
+
+  if (!m.pool_tag.application.empty()) {
     out << m.pool_tag;
   }
 
@@ -351,8 +355,9 @@ bool OSDCap::is_capable(const string& pool_name, const string& ns,
 {
   std::vector<bool> class_allowed(classes.size(), false);
   for (auto &grant : grants) {
-    if (grant.is_capable(pool_name, ns, pool_auid, application_metadata, object, op_may_read,
-                         op_may_write, classes, &class_allowed)) {
+    if (grant.is_capable(pool_name, ns, pool_auid, application_metadata,
+                        object, op_may_read, op_may_write, classes,
+                        &class_allowed)) {
       return true;
     }
   }
@@ -408,9 +413,11 @@ struct OSDCapParser : qi::grammar<Iterator, OSDCap()>
 
     match = (
       pooltag                                 [_val = phoenix::construct<OSDCapMatch>(_1)] |
+      (nspace >> pooltag)                     [_val = phoenix::construct<OSDCapMatch>(_1, _2)] |
       (auid >> object_prefix)                 [_val = phoenix::construct<OSDCapMatch>(_1, _2)] |
       (pool_name >> nspace >> object_prefix)  [_val = phoenix::construct<OSDCapMatch>(_1, _2, _3)] |
-      (pool_name >> object_prefix)            [_val = phoenix::construct<OSDCapMatch>(_1, _2)]);
+      (pool_name >> object_prefix)            [_val = phoenix::construct<OSDCapMatch>(_1, _2)]
+    );
 
     // rwxa := * | [r][w][x] [class-read] [class-write]
     rwxa =
@@ -487,4 +494,3 @@ bool OSDCap::parse(const string& str, ostream *err)
 
   return false; 
 }
-
index 2a37a28d35fd73ca89c4ba63b0550fda48c8ab23..59b8392f67e1953b9f0924f817fd165185215478 100644 (file)
@@ -139,6 +139,8 @@ struct OSDCapMatch {
   OSDCapMatch(const std::string& dummy, const std::string& app,
              const std::string& key, const std::string& val)
     : pool_tag(app, key, val) {}
+  OSDCapMatch(const std::string& ns, const OSDCapPoolTag& pt)
+    : pool_namespace("", ns), pool_tag(pt) {}
 
   /**
    * check if given request parameters match our constraints
index 2fae9e3cf1d9ac7132f27350444bd273850e6680..2d7629d1088de4000f8b28d2bfcb2aedff02e59f 100644 (file)
@@ -68,6 +68,8 @@ const char *parse_good[] = {
   "allow pool foo namespace=nfoo rwx ; allow pool bar namespace=nbar r",
   "allow pool foo namespace nfoo rwx ;allow pool bar namespace nbar r",
   "allow pool foo namespace=nfoo rwx; allow pool bar namespace nbar object_prefix rbd r",
+  "allow rwx namespace=nfoo tag cephfs data=cephfs_a",
+  "allow rwx namespace foo tag cephfs data =cephfs_a",
   "allow pool foo namespace=nfoo* rwx",
   "allow pool foo namespace=\"\" rwx; allow pool bar namespace='' object_prefix rbd r",
   "allow pool foo namespace \"\" rwx; allow pool bar namespace '' object_prefix rbd r",
@@ -827,6 +829,36 @@ TEST(OSDCap, PoolTagWildKV)
   ASSERT_TRUE(cap.is_capable("foo", "", 0, {{"application", {{"foo", "bar"}, {"key2", "value"}}}, {"app2", {{"foo", "bar"}}}}, "foo", true, true, {}));
 }
 
+TEST(OSDCap, NSPool)
+{
+  OSDCap cap;
+  ASSERT_TRUE(cap.parse("allow rwx namespace ns tag application key=value", NULL));
+
+  ASSERT_TRUE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {}));
+
+  ASSERT_FALSE(cap.is_capable("foo", "", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "ns2", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value2"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key2", "value"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "", 0, {}, "foo", true, true, {}));
+}
+
+TEST(OSDCap, NSPoolGlob)
+{
+  OSDCap cap;
+  ASSERT_TRUE(cap.parse("allow rwx namespace ns* tag application key=value", NULL));
+
+  ASSERT_TRUE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {}));
+
+  ASSERT_TRUE(cap.is_capable("foo", "ns2", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "", 0, {{"application", {{"key", "value"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key", "value2"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "ns", 0, {{"application", {{"key2", "value"}}}}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("foo", "", 0, {}, "foo", true, true, {}));
+}
+
 TEST(OSDCap, OutputParsed)
 {
   struct CapsTest {
@@ -875,7 +907,9 @@ TEST(OSDCap, OutputParsed)
     {"allow class-read object_prefix rbd_children, allow pool libvirt-pool-test rwx",
      "osdcap[grant(object_prefix rbd_children  class-read),grant(pool libvirt-pool-test rwx)]"},
     {"allow rwx tag application key=value",
-     "osdcap[grant(app application key key val value rwx)]"}
+     "osdcap[grant(app application key key val value rwx)]"},
+    {"allow rwx namespace ns* tag application key=value",
+     "osdcap[grant(namespace ns* app application key key val value rwx)]"}
   };
 
   size_t num_tests = sizeof(test_values) / sizeof(*test_values);