]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: allow wildcards for mon cap command matching
authorSage Weil <sage@newdream.net>
Tue, 23 Aug 2011 22:18:29 +0000 (15:18 -0700)
committerSage Weil <sage@newdream.net>
Tue, 23 Aug 2011 22:24:44 +0000 (15:24 -0700)
We need wildcards, actually.  * is any token, ... is 1 or more tokens.

Signed-off-by: Sage Weil <sage@newdream.net>
qa/workunits/caps/mon_commands.sh
src/mon/MonCaps.cc
src/mon/Monitor.cc

index b0aca22f2075e76dd90575abff1caf1a05b904c2..237055c3c1691a8f0e4e9c2aea2819792f1d88c3 100755 (executable)
@@ -1,18 +1,25 @@
 #!/bin/sh -ex
 
 cauthtool --create-keyring k --gen-key -p --name client.xx
-ceph auth add -i k client.xx mon 'allow command foo; allow command bar'
+ceph auth add -i k client.xx mon "allow command foo; allow command bar *; allow command baz ...; allow command foo add * mon allow\\ rwx osd allow\\ *"
 
-( ceph -k k -n client.xx foo || true ) | grep -v 'Access denied'
-( ceph -k k -n client.xx foo ooo || true ) | grep -v 'Access denied'
-( ceph -k k -n client.xx fo || true ) | grep 'Access denied'
-( ceph -k k -n client.xx fooo || true ) | grep 'Access denied'
+( ceph -k k -n client.xx foo      || true ) | grep 'unrecog'
+( ceph -k k -n client.xx foo ooo  || true ) | grep 'Access denied'
+( ceph -k k -n client.xx fo       || true ) | grep 'Access denied'
+( ceph -k k -n client.xx fooo     || true ) | grep 'Access denied'
 
-( ceph -k k -n client.xx bar || true ) | grep -v 'Access denied'
-( ceph -k k -n client.xx bar a b c || true ) | grep -v 'Access denied'
-( ceph -k k -n client.xx ba || true ) | grep 'Access denied'
-( ceph -k k -n client.xx barr || true ) | grep 'Access denied'
+( ceph -k k -n client.xx bar       || true ) | grep 'Access denied'
+( ceph -k k -n client.xx bar a     || true ) | grep 'unrecog'
+( ceph -k k -n client.xx bar a b c || true ) | grep 'Access denied'
+( ceph -k k -n client.xx ba        || true ) | grep 'Access denied'
+( ceph -k k -n client.xx barr      || true ) | grep 'Access denied'
 
-( ceph -k k -n client.xx baz || true ) | grep 'Access denied'
+( ceph -k k -n client.xx baz     || true ) | grep -v 'Access denied'
+( ceph -k k -n client.xx baz a   || true ) | grep -v 'Access denied'
+( ceph -k k -n client.xx baz a b || true ) | grep -v 'Access denied'
+
+( ceph -k k -n client.xx foo add osd.1 -i k mon 'allow rwx' osd 'allow *' || true ) | grep 'unrecog'
+( ceph -k k -n client.xx foo add osd a b c -i k mon 'allow rwx' osd 'allow *' || true ) | grep 'Access denied'
+( ceph -k k -n client.xx foo add osd a b c -i k mon 'allow *' || true ) | grep 'Access denied'
 
 echo OK
\ No newline at end of file
index 8948edc82a1742c3b204a78b0dc7177fae974536..c4abbe686ca82815c17d9230c1ff75295c15468d 100644 (file)
@@ -26,21 +26,30 @@ bool MonCaps::get_next_token(string s, size_t& pos, string& token)
   if (start < 0) {
     return false; 
   }
+  
+  token.clear();
 
-  if (s[start] == '=' || s[start] == ',' || s[start] == ';') {
-    end = start + 1;
-  } else {
-    end = s.find_first_of(";,= \t", start+1);
-  }
-
-  if (end < 0) {
-    end=s.size();
+  while (true) {
+    if (s[start] == '=' || s[start] == ',' || s[start] == ';') {
+      end = start + 1;
+    } else {
+      end = s.find_first_of(";,= \t", start+1);
+      if (end < 0) {
+       end = s.size();
+      }
+      else if (end >= start + 2 && s[end] == ' ' && s[end-1] == '\\') {
+       token += s.substr(start, end - start - 1);
+       token += ' ';
+       start = end + 1;
+       continue;
+      }
+    }
+    break;
   }
 
-  token = s.substr(start, end - start);
+  token += s.substr(start, end - start);
 
   pos = end;
-
   return true;
 }
 
@@ -112,8 +121,6 @@ bool MonCaps::parse(bufferlist::iterator& iter)
     bool op_deny = false;
     bool any_cmd = false;
     bool got_eq = false;
-    bool got_command = false;
-    list<string> command;
     list<int> services_list;
     list<int> uid_list;
     bool last_is_comma = false;
@@ -125,8 +132,6 @@ bool MonCaps::parse(bufferlist::iterator& iter)
         op_deny = false;
         any_cmd = false;
         got_eq = false;
-       got_command = false;
-       command.clear();
         last_is_comma = false;
         cap_val = 0;
         init = false;
@@ -147,7 +152,13 @@ do { \
          allow_all = true;
        } else if (token.compare("command") == 0) {
          ASSERT_STATE(op_allow);
-         got_command = true;
+         list<string> command;
+         while (get_next_token(s, pos, token)) {
+           if (token.compare(";") == 0)
+             break;
+           command.push_back(token);
+         }
+         cmd_allow.push_back(command);
        } else if (token.compare("=") == 0) {
           ASSERT_STATE(any_cmd);
           got_eq = true;
@@ -167,34 +178,26 @@ do { \
        } else if (is_rwx(token, cap_val)) {
           ASSERT_STATE(op_allow || op_deny);
         } else if (token.compare(";") != 0) {
-         if (got_command) {
-           command.push_back(token);
+         ASSERT_STATE(got_eq);
+         if (token.compare(",") == 0) {
+           ASSERT_STATE(!last_is_comma);
          } else {
-           ASSERT_STATE(got_eq);
-           if (token.compare(",") == 0) {
-             ASSERT_STATE(!last_is_comma);
-           } else {
-             last_is_comma = false;
-             int service = get_service_id(token);
-             if (service != -EINVAL) {
-               if (service >= 0) {
-                 services_list.push_back(service);
-               } else {
-                 generic_dout(0) << "error parsing caps at pos=" << pos << ", unknown service_name: " << token << dendl;
-               }
-             } else { //must be a uid
-               uid_list.push_back(strtoul(token.c_str(), NULL, 10));
+           last_is_comma = false;
+           int service = get_service_id(token);
+           if (service != -EINVAL) {
+             if (service >= 0) {
+               services_list.push_back(service);
+             } else {
+               generic_dout(0) << "error parsing caps at pos=" << pos << ", unknown service_name: " << token << dendl;
              }
+           } else { //must be a uid
+             uid_list.push_back(strtoul(token.c_str(), NULL, 10));
            }
           }
         }
 
         if (token.compare(";") == 0 || pos >= s.size()) {
-         if (got_command) {
-           generic_dout(0) << "parsed command " << command << dendl;
-           cmd_allow.push_back(command);
-         }
-         else if (got_eq) {
+         if (got_eq) {
             ASSERT_STATE((services_list.size() > 0) ||
                         (uid_list.size() > 0));
             
index 5058ecee3260c0dc759a2326087966672e088b6b..05b41cef075b7d52494a2cae4f9b13116889f003 100644 (file)
@@ -308,12 +308,19 @@ bool Monitor::_allowed_command(MonSession *s, const vector<string>& cmd)
        p != s->caps.cmd_allow.end();
        ++p) {
     list<string>::iterator q;
-    int i = 0;
-    for (q = p->begin(); q != p->end(); ++q, ++i) {
+    unsigned i;
+    dout(0) << "cmd " << cmd << " vs " << *p << dendl;
+    for (q = p->begin(), i = 0; q != p->end() && i < cmd.size(); ++q, ++i) {
+      if (*q == "*")
+       continue;
+      if (*q == "...") {
+       i = cmd.size() - 1;
+       continue;
+      }        
       if (*q != cmd[i])
        break;
     }
-    if (q == p->end())
+    if (q == p->end() && i == cmd.size())
       return true;   // match
   }