]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mon/AuthMonitor: automatically create initial keys
authorJoao Eduardo Luis <joao@suse.de>
Fri, 23 Feb 2018 20:28:55 +0000 (20:28 +0000)
committerJoao Eduardo Luis <joao@suse.de>
Fri, 6 Apr 2018 03:53:13 +0000 (04:53 +0100)
On first run as the leader, the monitor will create any missing
bootstrap keys, as well as the client.admin key if not present in the
mkfs keyring.

Signed-off-by: Joao Eduardo Luis <joao@suse.de>
src/auth/KeyRing.h
src/mon/AuthMonitor.cc
src/mon/AuthMonitor.h

index 002f67fffd84d546f72fd4ed2f5b27ea3a46510e..0326626ffaefd419d6656e0a131896b33b4c3a55 100644 (file)
@@ -38,6 +38,10 @@ public:
   void print(ostream& out);
 
   // accessors
+  bool exists(const EntityName& name) const {
+    auto p = keys.find(name);
+    return p != keys.end();
+  }
   bool get_auth(const EntityName& name, EntityAuth &a) const {
     map<EntityName, EntityAuth>::const_iterator k = keys.find(name);
     if (k == keys.end())
index 280d742a7fb1ed5134880c955551c4d2de6a727f..abfa86746477ab51360a0a8cf88bea9cb295a3a6 100644 (file)
@@ -83,6 +83,74 @@ void AuthMonitor::on_active()
   mon->key_server.start_server();
 }
 
+bufferlist _encode_cap(const string& cap)
+{
+  bufferlist bl;
+  encode(cap, bl);
+  return bl;
+}
+
+void AuthMonitor::get_initial_keyring(KeyRing *keyring)
+{
+  dout(10) << __func__ << dendl;
+  assert(keyring != nullptr);
+
+  bufferlist bl;
+  int ret = mon->store->get("mkfs", "keyring", bl);
+  if (ret == -ENOENT) {
+    return;
+  }
+  // fail hard only if there's an error we're not expecting to see
+  assert(ret == 0);
+
+  bufferlist::iterator p = bl.begin();
+  decode(*keyring, p);
+}
+
+void AuthMonitor::create_initial_keys(KeyRing *keyring)
+{
+  dout(10) << __func__ << dendl;
+
+  map<string,map<string,bufferlist> > bootstrap = {
+    { "admin", {
+      { "mon", _encode_cap("allow *") },
+      { "osd", _encode_cap("allow *") },
+      { "mds", _encode_cap("allow *") },
+      { "mgr", _encode_cap("allow *") }
+    } },
+    { "bootstrap-osd", {
+      { "mon", _encode_cap("allow profile bootstrap-osd") }
+    } },
+    { "bootstrap-rgw", {
+      { "mon", _encode_cap("allow profile bootstrap-rgw") }
+    } },
+    { "bootstrap-mds", {
+      { "mon", _encode_cap("allow profile bootstrap-mds") }
+    } },
+    { "bootstrap-mgr", {
+      { "mon", _encode_cap("allow profile bootstrap-mgr") }
+    } },
+    { "bootstrap-rbd", {
+      { "mon", _encode_cap("allow profile bootstrap-rbd") }
+    } }
+  };
+
+  for (auto &p : bootstrap) {
+    EntityName name;
+    name.from_str("client." + p.first);
+    if (keyring->exists(name)) {
+      continue;
+    }
+
+    dout(10) << __func__ << " creating entry for client." << p.first << dendl;
+    EntityAuth auth;
+    auth.key.create(g_ceph_context, CEPH_CRYPTO_AES);
+    auth.caps = p.second;
+
+    keyring->add(name, auth);
+  }
+}
+
 void AuthMonitor::create_initial()
 {
   dout(10) << "create_initial -- creating initial map" << dendl;
@@ -94,19 +162,12 @@ void AuthMonitor::create_initial()
 
   if (mon->is_keyring_required()) {
     KeyRing keyring;
-    bufferlist bl;
-    int ret = mon->store->get("mkfs", "keyring", bl);
-    // fail hard only if there's an error we're not expecting to see
-    assert((ret == 0) || (ret == -ENOENT));
-    
-    // try importing only if there's a key
-    if (ret == 0) {
-      KeyRing keyring;
-      bufferlist::iterator p = bl.begin();
-
-      decode(keyring, p);
-      import_keyring(keyring);
-    }
+    // attempt to obtain an existing mkfs-time keyring
+    get_initial_keyring(&keyring);
+    // create missing keys in the keyring
+    create_initial_keys(&keyring);
+    // import the resulting keyring
+    import_keyring(keyring);
   }
 
   max_global_id = MIN_GLOBAL_ID;
@@ -849,13 +910,6 @@ int AuthMonitor::do_osd_destroy(
   return 0;
 }
 
-bufferlist _encode_cap(const string& cap)
-{
-  bufferlist bl;
-  encode(cap, bl);
-  return bl;
-}
-
 int _create_auth(
     EntityAuth& auth,
     const string& key,
@@ -1440,6 +1494,14 @@ bool AuthMonitor::prepare_global_id(MonOpRequestRef op)
 
 void AuthMonitor::upgrade_format()
 {
+  // NOTE: make sure we either *always* get a bootstrap-mgr key if it doesn't
+  // exist when we upgrade, or that it already exists.
+  //
+  // <sage> joao: one thing is i think maybe we should create the key on
+  // upgrade if it doesn't exist.  right now it only happens on upgrade from
+  // kraken->luminous, but ironically i think fresh luminous clusters that
+  // don't use ceph-deploy might be missing it.
+
   unsigned int current = 2;
   if (!mon->get_quorum_mon_features().contains_all(
        ceph::features::mon::FEATURE_LUMINOUS)) {
index 1304c80d2f45f0fa1c66720e206d2c4acd67e0a0..dae298fee6448fcfbc0078124b184e46f8ce3390 100644 (file)
@@ -144,6 +144,8 @@ private:
 
   void on_active() override;
   bool should_propose(double& delay) override;
+  void get_initial_keyring(KeyRing *keyring);
+  void create_initial_keys(KeyRing *keyring);
   void create_initial() override;
   void update_from_paxos(bool *need_bootstrap) override;
   void create_pending() override;  // prepare a new pending