]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
OSD/OSDCap: Namespace globbing
authorDouglas Fuller <dfuller@redhat.com>
Mon, 9 Oct 2017 19:18:43 +0000 (15:18 -0400)
committerDouglas Fuller <dfuller@redhat.com>
Wed, 25 Oct 2017 19:34:13 +0000 (15:34 -0400)
Permit the wildcard * at the end of namespace names to match any
namespace starting with the given prefix. The wildcard is only
allowed at the end of the namespace name.

Example:

allow rw namespace=foo*

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

index f3e406b1ec279815d7aed765f63d9b797f72ea93..a3e719e29b002dcc04c289ddf1257d2db5f09e35 100644 (file)
@@ -140,7 +140,8 @@ 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> ]
+                    | tag <application-name> <key>=<value> 
+                    | namespace[=]<rados-namespace> ]
         capspec := * | [r][w][x] [class-read] [class-write]
 
 The capspec determines what kind of operations the entity can perform::
index aac6ef0c7149ad1e096530e26302f79a7aebb172..33b58c02252aff440a71c97eb5453c5e5e113ff0 100644 (file)
@@ -248,6 +248,11 @@ namespace to the object name with out the computational overhead of a separate
 pool. Rather than creating a separate pool for a user or set of users, you may
 use a namespace. **Note:** Only available using ``librados`` at this time.
 
+Access may be restricted to specific RADOS namespaces using the ``namespace``
+capability. Limited globbing of namespaces is supported; if the last character
+of the specified namespace is ``*``, then access is granted to any namespace
+starting with the provided argument.
+
 
 Managing Users
 ==============
index 5603e675caa330883bf2328d7189bf793e42b84b..d868c2c2ee5c7af69613e12cc57c769094c87b91 100644 (file)
@@ -6701,11 +6701,13 @@ bool OSD::ms_verify_authorizer(Connection *con, int peer_type,
       catch (buffer::error& e) {
         isvalid = false;
       }
-      bool success = s->caps.parse(str);
+      stringstream ss;
+      bool success = s->caps.parse(str, &ss);
       if (success)
        dout(10) << " session " << s << " " << s->entity_name << " has caps " << s->caps << " '" << str << "'" << dendl;
       else {
        dout(10) << " session " << s << " " << s->entity_name << " failed to parse caps '" << str << "'" << dendl;
+       dout(20) << "parser returned " << ss.str() << dendl;
         isvalid = false;
       }
     }
index fd0857336b108940899c23e3e7371f99db303e71..e0d028d17704257bb26146c5e22d4a481f201cb2 100644 (file)
@@ -16,6 +16,7 @@
 #include <boost/spirit/include/qi.hpp>
 #include <boost/spirit/include/phoenix_operator.hpp>
 #include <boost/spirit/include/phoenix.hpp>
+#include <boost/algorithm/string/predicate.hpp>
 
 #include "OSDCap.h"
 #include "common/config.h"
@@ -109,6 +110,11 @@ bool OSDCapPoolNamespace::is_match(const std::string& pn,
     }
   }
   if (nspace) {
+    if ((*nspace)[nspace->length() - 1] == '*' &&
+       boost::starts_with(ns, nspace->substr(0, nspace->length() - 1))) {
+      return true;
+    }
+
     if (*nspace != ns) {
       return false;
     }
@@ -388,7 +394,9 @@ struct OSDCapParser : qi::grammar<Iterator, OSDCap()>
     spaces = +ascii::space;
 
     pool_name %= -(spaces >> lit("pool") >> (lit('=') | spaces) >> str);
-    nspace %= (spaces >> lit("namespace") >> (lit('=') | spaces) >> estr);
+    nspace %= (spaces >> lit("namespace")
+              >> (lit('=') | spaces)
+              >> estr >> -char_('*'));
 
     // match := [pool[=]<poolname> [namespace[=]<namespace>] | auid <123>] [object_prefix <prefix>]
     auid %= (spaces >> lit("auid") >> spaces >> int_);
index dd5ea7accbff117ef4ae1a0a27b73436b0572dd4..2fae9e3cf1d9ac7132f27350444bd273850e6680 100644 (file)
@@ -68,6 +68,7 @@ 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 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",
   "profile abc, profile abc pool=bar, profile abc pool=bar namespace=foo",
@@ -108,6 +109,7 @@ const char *parse_bad[] = {
   "allow rwx namespace",
   "allow namespace",
   "allow namespace=foo",
+  "allow namespace=f*oo",
   "allow rwx auid 123 namespace asdf",
   "allow wwx pool ''",
   "allow rwx tag application key value",
@@ -278,6 +280,26 @@ TEST(OSDCap, ObjectPoolAndPrefix) {
   ASSERT_FALSE(cap.is_capable("baz", "", 0, {}, "fo", true, true, {{"cls", true, true, true}}));
 }
 
+TEST(OSDCap, Namespace) {
+  OSDCap cap;
+  ASSERT_TRUE(cap.parse("allow rw namespace=nfoo"));
+
+  ASSERT_TRUE(cap.is_capable("bar", "nfoo", 0, {}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("bar", "", 0, {}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("bar", "nfoobar", 0, {}, "foo", true, true, {}));
+}
+
+TEST(OSDCap, NamespaceGlob) {
+  OSDCap cap;
+  ASSERT_TRUE(cap.parse("allow rw namespace=nfoo*"));
+
+  ASSERT_TRUE(cap.is_capable("bar", "nfoo", 0, {}, "foo", true, true, {}));
+  ASSERT_TRUE(cap.is_capable("bar", "nfoobar", 0, {}, "foo", true, true, {}));
+
+  ASSERT_FALSE(cap.is_capable("bar", "", 0, {}, "foo", true, true, {}));
+  ASSERT_FALSE(cap.is_capable("bar", "nfo", 0, {}, "foo", true, true, {}));
+}
+
 TEST(OSDCap, BasicR) {
   OSDCap cap;
   ASSERT_TRUE(cap.parse("allow r", NULL));