]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/AuthMonitor: Add special syntax for cephfs
authorDouglas Fuller <dfuller@redhat.com>
Tue, 1 Aug 2017 20:32:38 +0000 (16:32 -0400)
committerDouglas Fuller <dfuller@redhat.com>
Wed, 2 Aug 2017 20:00:53 +0000 (16:00 -0400)
Add a new command, ceph auth fs, to generate and apply auth caps for
cephfs.

Syntax:

  ceph auth fs <fs_name> <entity_name> (<dir> <cap>)...

Notes:

  In this case, the AuthMonitor will determine the correct osd and
  mds cap syntax based on the data pools used by <fs_name>. The same
  caps will be applied to all data pools regardless of the filesystem
  configuration. If the write cap is enabled on any directory, the write
  cap for every data pool will be obtained.

  If different auth caps for this entity already exist, the result is
  -EINVAL.

Fixes: http://tracker.ceph.com/issues/20885
Signed-off-by: Douglas Fuller <dfuller@redhat.com>
fixup

src/mon/AuthMonitor.cc
src/mon/MonCommands.h
src/mon/Monitor.cc

index 817e13d05542fbf4b3f3284466be8414693b6cb5..c9c836dc5151d99bedb09bcd156ce822575c6665 100644 (file)
@@ -19,6 +19,7 @@
 #include "mon/MonitorDBStore.h"
 #include "mon/ConfigKeyService.h"
 #include "mon/OSDMonitor.h"
+#include "mon/MDSMonitor.h"
 
 #include "messages/MMonCommand.h"
 #include "messages/MAuth.h"
@@ -538,6 +539,7 @@ bool AuthMonitor::preprocess_command(MonOpRequestRef op)
       prefix == "auth rm" ||
       prefix == "auth get-or-create" ||
       prefix == "auth get-or-create-key" ||
+      prefix == "fs authorize" ||
       prefix == "auth import" ||
       prefix == "auth caps") {
     return false;
@@ -1271,6 +1273,98 @@ bool AuthMonitor::prepare_command(MonOpRequestRef op)
     wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, rdata,
                                              get_last_committed() + 1));
     return true;
+  } else if (prefix == "fs authorize") {
+    string filesystem;
+    cmd_getval(g_ceph_context, cmdmap, "filesystem", filesystem);
+    string mds_cap_string, osd_cap_string;
+    string osd_cap_wanted = "r";
+
+    for (auto it = caps_vec.begin();
+        it != caps_vec.end() && (it + 1) != caps_vec.end();
+        it += 2) {
+      const string &path = *it;
+      const string &cap = *(it+1);
+      if (cap != "r" && cap != "rw" && cap != "rwp") {
+       ss << "Only 'r', 'rw', and 'rwp' permissions are allowed for filesystems.";
+       err = -EINVAL;
+       goto done;
+      }
+      if (cap.find('w') != string::npos) {
+       osd_cap_wanted = "rw";
+      }
+
+      mds_cap_string += mds_cap_string.empty() ? "" : ", ";
+      mds_cap_string += "allow " + cap;
+      if (path != "/") {
+       mds_cap_string += " path=" + path;
+      }
+    }
+
+    auto fs = mon->mdsmon()->get_fsmap().get_filesystem(filesystem);
+    if (!fs) {
+      ss << "filesystem " << filesystem << " does not exist.";
+      err = -EINVAL;
+      goto done;
+    }
+
+    auto data_pools = fs->mds_map.get_data_pools();
+    for (auto p : data_pools) {
+      const string &pool_name = mon->osdmon()->osdmap.get_pool_name(p);
+      osd_cap_string += osd_cap_string.empty() ? "" : ", ";
+      osd_cap_string += "allow " + osd_cap_wanted + " pool=" + pool_name;
+    }
+
+    std::map<string, bufferlist> wanted_caps = {
+      { "mon", _encode_cap("allow r") },
+      { "osd", _encode_cap(osd_cap_string) },
+      { "mds", _encode_cap(mds_cap_string) }
+    };
+
+    EntityAuth entity_auth;
+    if (mon->key_server.get_auth(entity, entity_auth)) {
+      for (const auto &sys_cap : wanted_caps) {
+       if (entity_auth.caps.count(sys_cap.first) == 0 ||
+           !entity_auth.caps[sys_cap.first].contents_equal(sys_cap.second)) {
+         ss << "key for " << entity << " exists but cap " << sys_cap.first
+            << " does not match";
+         err = -EINVAL;
+         goto done;
+       }
+      }
+
+      KeyRing kr;
+      kr.add(entity, entity_auth.key);
+      if (f) {
+       kr.set_caps(entity, entity_auth.caps);
+       kr.encode_formatted("auth", f.get(), rdata);
+      } else {
+       kr.encode_plaintext(rdata);
+      }
+      err = 0;
+      goto done;
+    }
+
+    KeyServerData::Incremental auth_inc;
+    auth_inc.op = KeyServerData::AUTH_INC_ADD;
+    auth_inc.name = entity;
+    auth_inc.auth.key.create(g_ceph_context, CEPH_CRYPTO_AES);
+    auth_inc.auth.caps = wanted_caps;
+
+    push_cephx_inc(auth_inc);
+    KeyRing kr;
+    kr.add(entity, auth_inc.auth.key);
+    if (f) {
+      kr.set_caps(entity, wanted_caps);
+      kr.encode_formatted("auth", f.get(), rdata);
+    } else {
+      kr.encode_plaintext(rdata);
+    }
+
+    rdata.append(ds);
+    getline(ss, rs);
+    wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs, rdata,
+                                                 get_last_committed() + 1));
+    return true;
   } else if (prefix == "auth caps" && !entity_name.empty()) {
     KeyServerData::Incremental auth_inc;
     auth_inc.name = entity;
index 97d77d625eb8b7b719db14075c395fb25fa5e897..505314b1c0f477e9864107a8e2b7d63624dd24fa 100644 (file)
@@ -175,6 +175,12 @@ COMMAND("auth get-or-create " \
        "name=caps,type=CephString,n=N,req=false", \
        "add auth info for <entity> from input file, or random key if no input given, and/or any caps specified in the command", \
        "auth", "rwx", "cli,rest")
+COMMAND("fs authorize " \
+   "name=filesystem,type=CephString " \
+   "name=entity,type=CephString " \
+       "name=caps,type=CephString,n=N", \
+       "add auth for <entity> to access file system <filesystem> based on following directory and permissions pairs", \
+       "auth", "rwx", "cli,rest")
 COMMAND("auth caps " \
        "name=entity,type=CephString " \
        "name=caps,type=CephString,n=N", \
index 692c170b65574559bc0bf0a397462b71dac83178..23d0c96fa159f9e60a7df44fec0e2dbb830b4045 100644 (file)
@@ -3128,7 +3128,8 @@ void Monitor::handle_command(MonOpRequestRef op)
     return;
   }
 
-  if (module == "mds" || module == "fs") {
+  if ((module == "mds" || module == "fs")  &&
+      prefix != "fs authorize") {
     mdsmon()->dispatch(op);
     return;
   }
@@ -3157,7 +3158,7 @@ void Monitor::handle_command(MonOpRequestRef op)
     monmon()->dispatch(op);
     return;
   }
-  if (module == "auth") {
+  if (module == "auth" || prefix == "fs authorize") {
     authmon()->dispatch(op);
     return;
   }