]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
auth: use KeyRing encode/decode
authorSage Weil <sage@newdream.net>
Thu, 4 Feb 2010 00:12:17 +0000 (16:12 -0800)
committerSage Weil <sage@newdream.net>
Thu, 4 Feb 2010 00:40:16 +0000 (16:40 -0800)
src/Makefile.am
src/auth/Auth.h
src/auth/KeyRing.cc
src/auth/KeyRing.h
src/authtool.cc
src/common/common_init.cc
src/mon/AuthMonitor.cc
src/mon/AuthMonitor.h

index 214e0fedc0530398a8cd2479b9feccd88fe041ed..e3eba743d85f01be105d351178cd452fe03ece6a 100644 (file)
@@ -59,7 +59,7 @@ streamtest_LDADD = libos.a libcommon.a -lpthread -lm -lcrypto
 bin_PROGRAMS += dumpjournal dupstore streamtest
 
 test_trans_SOURCES = test_trans.cc
-test_trans_LDADD = libos.a libcommon.a -lpthread -lm
+test_trans_LDADD = libos.a libcommon.a -lpthread -lm -lcrypto
 bin_PROGRAMS += test_trans
 
 # synthetic client
index f5ad358cbc84f8be666a937bf5c6a67bba09c4f7..60b9455241ea11237f9742e6602a63d61ffda7ef 100644 (file)
@@ -50,7 +50,7 @@ struct EntityName {
     return s;
   }
 
-  bool from_str(string& s) {
+  bool from_str(const string& s) {
     int pos = s.find('.');
 
     if (pos < 0)
index ba06efc55b127d33f68814d4e019845e2c9d1b67..3c6632699bb23cedf86fc3b0097d5b1b0e689adc 100644 (file)
@@ -30,76 +30,75 @@ using namespace std;
 
 KeyRing g_keyring;
 
-bool KeyRing::load_master(const char *filename_list)
+bool KeyRing::load(const char *filename_list)
 {
   string k = filename_list;
   string filename;
   list<string> ls;
   get_str_list(k, ls);
-  int fd = -1;
+  bufferlist bl;
+  bool loaded = false;
   for (list<string>::iterator p = ls.begin(); p != ls.end(); p++) {
     // subst in home dir?
     size_t pos = p->find("~/");
     if (pos != string::npos)
       p->replace(pos, 1, getenv("HOME"));
 
-    fd = open(p->c_str(), O_RDONLY);
-    if (fd >= 0) {
+    if (bl.read_file(p->c_str(), true) == 0) {
+      loaded = true;
       filename = *p;
       break;
     }
   }
-  if (fd < 0) {
+  if (!loaded) {
     dout(0) << "can't open key file(s) " << filename_list << dendl;
     return false;
   }
 
-  // get size
-  struct stat st;
-  int rc = fstat(fd, &st);
-  if (rc != 0) {
-    dout(0) << "error stat'ing key file " << filename << dendl;
-    return false;
-  }
-  __int32_t len = st.st_size;
-  bufferlist bl;
+  bufferlist::iterator p = bl.begin();
+  decode(p);
 
-  bufferptr bp(len);
-  int off = 0;
-  while (off < len) {
-    int r = read(fd, bp.c_str()+off, len-off);
-    if (r < 0) {
-      derr(0) << "errno on read " << strerror(errno) << dendl;
-      return false;
+  dout(1) << "loaded key file " << filename << dendl;
+  return true;
+}
+
+void KeyRing::print(ostream& out)
+{
+  for (map<string, EntityAuth>::iterator p = keys.begin();
+       p != keys.end();
+       ++p) {
+    string n = p->first;
+    if (n.empty()) {
+      out << "<default key>" << std::endl;
+    } else {
+      out << n << std::endl;
+    }
+    out << "\tkey: " << p->second.key << std::endl;
+
+    for (map<string, bufferlist>::iterator q = p->second.caps.begin();
+        q != p->second.caps.end();
+        ++q) {
+      bufferlist::iterator dataiter = q->second.begin();
+      string caps;
+      ::decode(caps, dataiter);
+      out << "\tcaps: [" << q->first << "] " << caps << std::endl;
     }
-    off += r;
   }
-  bl.append(bp);
-  close(fd);
-
-  bufferlist::iterator iter = bl.begin();
-
-  map<string, EntityAuth> m;
-  map<string, EntityAuth>::iterator miter;
-
-  ::decode(m, iter);
-
-  string name = g_conf.entity_name->to_str();
-
-  dout(10) << "looking for key entry name=" << name << dendl;
+}
 
-  miter = m.find(name);
-  if (miter == m.end()) {
-    miter = m.find("");
-    if (miter == m.end())
-      return false; 
+void KeyRing::import(KeyRing& other)
+{
+  for (map<string, EntityAuth>::iterator p = other.keys.begin();
+       p != other.keys.end();
+       ++p) {
+    dout(10) << " importing " << p->first << " " << p->second << dendl;
+    keys[p->first] = p->second;
   }
-  master = miter->second.key;
-  dout(1) << "loaded key file " << filename << dendl;
-  return true;
 }
 
+// ----------------
+// rotating crap
+
 void KeyRing::set_rotating(RotatingSecrets& secrets)
 {
   Mutex::Locker l(lock);
@@ -122,13 +121,6 @@ void KeyRing::set_rotating(RotatingSecrets& secrets)
   }
 }
 
-void KeyRing::get_master(CryptoKey& dest)
-{
-  Mutex::Locker l(lock);
-
-  dest = master;
-}
-
 bool KeyRing::need_rotating_secrets()
 {
   Mutex::Locker l(lock);
@@ -182,3 +174,4 @@ bool KeyRing::get_service_secret(uint32_t service_id, uint64_t secret_id, Crypto
   return false;
 }
 
+
index 879bd530a1c8ca47ebd74f7dbe92a827db5daa55..e81a8d61e142cf2ad171fdbaf67ba8be751e30cc 100644 (file)
 */
 
 class KeyRing : public KeyStore {
-  CryptoKey master;
+  map<string, EntityAuth> keys;
   RotatingSecrets rotating_secrets;
   Mutex lock;
 public:
   KeyRing() : lock("KeyRing") {}
 
-  bool load_master(const char *filename);
-  void set_rotating(RotatingSecrets& secrets);
-
-  void get_master(CryptoKey& dest);
+  map<string, EntityAuth>& get_keys() { return keys; }  // yuck
 
-  bool need_rotating_secrets();
+  bool load(const char *filename);
+  void print(ostream& out);
 
+  bool get_auth(EntityName& name, EntityAuth &a) {
+    string n = name.to_str();
+    if (keys.count(n)) {
+      a = keys[n];
+      return true;
+    }
+    return false;
+  }
   bool get_secret(EntityName& name, CryptoKey& secret) {
-    get_master(secret);
-    return true;
+    string n = name.to_str();
+    if (keys.count(n)) {
+      secret = keys[n].key;
+      return true;
+    }
+    return false;
+  }
+  void get_master(CryptoKey& dest) {
+    get_secret(*g_conf.entity_name, dest);
+  }
+
+  //
+  void add(EntityName& name, EntityAuth &a) {
+    string s = name.to_str();
+    keys[s] = a;
   }
+  void set_caps(EntityName& name, map<string, bufferlist>& caps) {
+    string s = name.to_str();
+    keys[s].caps = caps;
+  }
+  void import(KeyRing& other);
+
+  // weirdness
+  void set_rotating(RotatingSecrets& secrets);
+  bool need_rotating_secrets();
   bool get_service_secret(uint32_t service_id, uint64_t secret_id, CryptoKey& secret);
+
+  void encode(bufferlist& bl) const {
+    __u8 v = 1;
+    ::encode(v, bl);
+    ::encode(keys, bl);
+  }
+  void decode(bufferlist::iterator& bl) {
+    __u8 v;
+    ::decode(v, bl);
+    ::decode(keys, bl);
+  }
 };
+WRITE_CLASS_ENCODER(KeyRing)
 
 extern KeyRing g_keyring;
 
index 8742fd3747b9a885358e4bfc0cb39335f891279c..e88856db66d9f7986bc768ce0c1c6f61f79e58df 100644 (file)
@@ -20,6 +20,7 @@ using namespace std;
 #include "common/common_init.h"
 #include "auth/Crypto.h"
 #include "auth/Auth.h"
+#include "auth/KeyRing.h"
 
 void usage()
 {
@@ -40,10 +41,11 @@ int main(int argc, const char **argv)
   const char *fn = 0;
   bool gen_key = false;
   bool list = false;
-  bool print_key = true;
+  bool print_key = false;
   bool create_keyring = false;
   const char *name = "";
   const char *caps_fn = NULL;
+  const char *import_keyring = NULL;
 
   FOR_EACH_ARG(args) {
     if (CONF_ARG_EQ("gen-key", 'g')) {
@@ -58,6 +60,8 @@ int main(int argc, const char **argv)
       CONF_SAFE_SET_ARG_VAL(&print_key, OPT_BOOL);
     } else if (CONF_ARG_EQ("create-keyring", 'c')) {
       CONF_SAFE_SET_ARG_VAL(&create_keyring, OPT_BOOL);
+    } else if (CONF_ARG_EQ("import-keyring", '\0')) {
+      CONF_SAFE_SET_ARG_VAL(&import_keyring, OPT_STR);
     } else if (!fn) {
       fn = args[i];
     } else 
@@ -68,8 +72,11 @@ int main(int argc, const char **argv)
     usage();
   }
 
-  map<string, EntityAuth> keys_map;
+  bool modified = false;
+  KeyRing keyring;
   string s = name;
+  EntityName ename;
+  ename.from_str(s);
 
   if (caps_fn) {
     if (!name || !(*name)) {
@@ -79,61 +86,76 @@ int main(int argc, const char **argv)
   }
 
   bufferlist bl;
-  int r = bl.read_file(fn, true);
-  if (r >= 0) {
-    try {
-      bufferlist::iterator iter = bl.begin();
-      ::decode(keys_map, iter);
-    } catch (buffer::error *err) {
-      cerr << "error reading file " << fn << std::endl;
-      exit(1);
-    }
-  } else if (create_keyring && r == -ENOENT) {
+  int r = 0;
+  if (create_keyring) {
     cout << "creating " << fn << std::endl;
   } else {
-    cerr << "can't open " << fn << ": " << strerror(errno) << std::endl;
-    exit(1);
+    r = bl.read_file(fn, true);
+    if (r >= 0) {
+      try {
+       bufferlist::iterator iter = bl.begin();
+       ::decode(keyring, iter);
+      } catch (buffer::error *err) {
+       cerr << "error reading file " << fn << std::endl;
+       exit(1);
+      }
+    } else {
+      cerr << "can't open " << fn << ": " << strerror(-r) << std::endl;
+      exit(1);
+    }
   }
 
   if (gen_key) {
-    CryptoKey key;
-    key.create(CEPH_CRYPTO_AES);
-    keys_map[s].key = key;
+    EntityAuth eauth;
+    eauth.key.create(CEPH_CRYPTO_AES);
+    keyring.add(ename, eauth);
+    modified = true;
   } else if (list) {
-    map<string, EntityAuth>::iterator iter = keys_map.begin();
-    for (; iter != keys_map.end(); ++iter) {
-      string n = iter->first;
-      if (n.empty()) {
-        cout << "<default key>" << std::endl;
-      } else {
-        cout << n << std::endl;
-      }
-      cout << "\tkey: " << iter->second.key << std::endl;
-      map<string, bufferlist>::iterator capsiter = iter->second.caps.begin();
-      for (; capsiter != iter->second.caps.end(); ++capsiter) {
-        bufferlist::iterator dataiter = capsiter->second.begin();
-        string caps;
-        ::decode(caps, dataiter);
-       cout << "\tcaps: [" << capsiter->first << "] " << caps << std::endl;
-      }
-    }
+    keyring.print(cout);
   } else if (print_key) {
-    if (keys_map.count(s)) {
+    CryptoKey key;
+    if (keyring.get_secret(ename, key)) {
       string a;
-      keys_map[s].key.encode_base64(a);
+      key.encode_base64(a);
       cout << a << std::endl;
+    } else {
+      cerr << "entity " << ename << " not found" << std::endl;
     }
-    else
-      cerr << "entity " << s << " not found" << std::endl;
+  } else if (import_keyring) {
+    KeyRing other;
+    bufferlist obl;
+    int r = obl.read_file(import_keyring);
+    if (r >= 0) {
+      try {
+       bufferlist::iterator iter = obl.begin();
+       ::decode(other, iter);
+      } catch (buffer::error *err) {
+       cerr << "error reading file " << import_keyring << std::endl;
+       exit(1);
+      }
+      
+      cout << "importing contents of " << import_keyring << " into " << fn << std::endl;
+      //other.print(cout);
+      keyring.import(other);
+      modified = true;
+
+    } else {
+      cerr << "can't open " << import_keyring << ": " << strerror(-r) << std::endl;
+      exit(1);
+    }
+  } else {
+    cerr << "no command specified" << std::endl;
+    usage();
   }
 
+
   if (caps_fn) {
-    map<string, bufferlist>& caps = keys_map[s].caps;
     ConfFile *cf = new ConfFile(caps_fn);
     if (!cf->parse()) {
       cerr << "could not parse caps file " << caps_fn << std::endl;
       exit(1);
     }
+    map<string, bufferlist> caps;
     const char *key_names[] = { "mon", "osd", "mds", NULL };
     for (int i=0; key_names[i]; i++) {
       char *val;
@@ -146,16 +168,18 @@ int main(int argc, const char **argv)
         free(val);
       }
     }
+    keyring.set_caps(ename, caps);
+    modified = true;
   }
 
-  if (gen_key) {
-    bufferlist bl2;
-    ::encode(keys_map, bl2);
-    r = bl2.write_file(fn);
-
+  if (modified) {
+    bufferlist bl;
+    ::encode(keyring, bl);
+    r = bl.write_file(fn);
     if (r < 0) {
       cerr << "could not write " << fn << std::endl;
     }
+    //cout << "wrote " << bl.length() << " bytes to " << fn << std::endl;
   }
 
   return 0;
index 8cc2485c8ba235d6ab07bd98273c6bad25c00cb6..049395e293f06e2bdcb8d886b364e4ac7f073991 100644 (file)
@@ -33,7 +33,7 @@ void common_init(std::vector<const char*>& args, const char *module_type, bool d
     _dout_open_log();
 
   if (init_keys && is_supported_auth(CEPH_AUTH_CEPHX)) {
-    g_keyring.load_master(g_conf.keyring);
+    g_keyring.load(g_conf.keyring);
   }
 }
 
index 8d9bb822d09a584f9e107fc66eaf2ca2aa7a1a64..f4052a9a34d4f549dcb0eac2d629bc340cdd6d5f 100644 (file)
@@ -26,6 +26,7 @@
 #include "common/Timer.h"
 
 #include "auth/AuthServiceHandler.h"
+#include "auth/KeyRing.h"
 
 #include "osd/osd_types.h"
 #include "osd/PG.h"  // yuck
@@ -93,7 +94,6 @@ void AuthMonitor::create_initial(bufferlist& bl)
 {
   dout(0) << "create_initial -- creating initial map" << dendl;
   if (g_conf.keyring) {
-    map<string, EntityAuth> keys_map;
     dout(0) << "reading initial keyring " << dendl;
     bufferlist bl;
 
@@ -105,32 +105,19 @@ void AuthMonitor::create_initial(bufferlist& bl)
       if ((r = bl.read_file(g_conf.keyring)) >= 0)
        break;
     if (r >= 0) {
+      KeyRing keyring;
       bool read_ok = false;
       try {
         bufferlist::iterator iter = bl.begin();
-        ::decode(keys_map, iter);
+        ::decode(keyring, iter);
         read_ok = true;
       } catch (buffer::error *err) {
         cerr << "error reading file " << g_conf.keyring << std::endl;
       }
       if (read_ok) {
-        map<string, EntityAuth>::iterator iter = keys_map.begin();
-        for (; iter != keys_map.end(); ++iter) {
-          string n = iter->first;
-          if (!n.empty()) {
-            dout(0) << "read key for entry: " << n << dendl;
-           KeyServerData::Incremental auth_inc;
-            if (!auth_inc.name.from_str(n)) {
-              dout(0) << "bad entity name " << n << dendl;
-              continue;
-            }
-            auth_inc.auth = iter->second; 
-            auth_inc.op = KeyServerData::AUTH_INC_ADD;
-            push_cephx_inc(auth_inc);
-          }
-        }
+       string def;
+       import_keyring(keyring, def);
       }
-
     }
   }
 
@@ -489,6 +476,30 @@ bool AuthMonitor::preprocess_command(MMonCommand *m)
   return true;
 }
 
+void AuthMonitor::import_keyring(KeyRing& keyring, string& def)
+{
+  for (map<string, EntityAuth>::iterator p = keyring.get_keys().begin();
+       p != keyring.get_keys().end();
+       p++) {
+    KeyServerData::Incremental auth_inc;
+    if (p->first.empty()) {
+      if (def.empty())
+       continue;
+      if (!auth_inc.name.from_str(def)) {
+       dout(0) << "bad entity name" << def << dendl;
+      }
+    } else {
+      if (!auth_inc.name.from_str(p->first)) {
+       dout(0) << "bad entity name " << p->first << dendl;
+       continue;
+      }
+    }
+    auth_inc.auth = p->second; 
+    auth_inc.op = KeyServerData::AUTH_INC_ADD;
+    dout(10) << " importing " << auth_inc.name << " " << auth_inc.auth << dendl;
+    push_cephx_inc(auth_inc);
+  }
+}
 
 bool AuthMonitor::prepare_command(MMonCommand *m)
 {
@@ -513,30 +524,16 @@ bool AuthMonitor::prepare_command(MMonCommand *m)
       bufferlist bl = m->get_data();
       dout(0) << "AuthMonitor::prepare_command bl.length()=" << bl.length() << dendl;
       bufferlist::iterator iter = bl.begin();
-      map<string, EntityAuth> crypto_map;
+      KeyRing keyring;
       try {
-        ::decode(crypto_map, iter);
+        ::decode(keyring, iter);
       } catch (buffer::error *err) {
-        ss << "error decoding key";
+        ss << "error decoding keyring";
         rs = -EINVAL;
         goto done;
       }
 
-      for (map<string, EntityAuth>::iterator miter = crypto_map.begin(); miter != crypto_map.end(); ++miter) {
-       KeyServerData::Incremental auth_inc;
-        dout(0) << "storing auth for " << entity_name  << dendl;
-        if (miter->first.empty()) {
-          if (entity_name.empty())
-            continue;
-          auth_inc.name.from_str(entity_name);
-        } else {
-          string s = miter->first;
-          auth_inc.name.from_str(s);
-        }
-        auth_inc.auth = miter->second;
-        auth_inc.op = KeyServerData::AUTH_INC_ADD;
-        push_cephx_inc(auth_inc);
-      }
+      import_keyring(keyring, entity_name);
       ss << "updated";
       getline(ss, rs);
       paxos->wait_for_commit(new Monitor::C_Command(mon, m, 0, rs, paxos->get_version()));
index 011e46606f17f10c5fa3b8c0a7f5f5e4f466d30b..e5bb5e70b7fbebf5d7ed515034c1cb563de21108 100644 (file)
@@ -28,6 +28,7 @@ class MMonCommand;
 class MAuth;
 class MAuthMon;
 class MMonGlobalID;
+class KeyRing;
 
 #define MIN_GLOBAL_ID 0x1000
 
@@ -78,6 +79,8 @@ private:
   uint64_t max_global_id;
   uint64_t last_allocated_id;
 
+  void import_keyring(KeyRing& keyring, string& def);
+
   void push_cephx_inc(KeyServerData::Incremental& auth_inc) {
     Incremental inc;
     inc.inc_type = AUTH_DATA;