From: Joao Eduardo Luis Date: Fri, 23 Feb 2018 20:28:55 +0000 (+0000) Subject: mon/AuthMonitor: automatically create initial keys X-Git-Tag: v13.1.0~310^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=595317c2e8ad6ad309c07c225f78903ba2c72d04;p=ceph.git mon/AuthMonitor: automatically create initial keys 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 --- diff --git a/src/auth/KeyRing.h b/src/auth/KeyRing.h index 002f67fffd8..0326626ffae 100644 --- a/src/auth/KeyRing.h +++ b/src/auth/KeyRing.h @@ -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::const_iterator k = keys.find(name); if (k == keys.end()) diff --git a/src/mon/AuthMonitor.cc b/src/mon/AuthMonitor.cc index 280d742a7fb..abfa8674647 100644 --- a/src/mon/AuthMonitor.cc +++ b/src/mon/AuthMonitor.cc @@ -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 > 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. + // + // 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)) { diff --git a/src/mon/AuthMonitor.h b/src/mon/AuthMonitor.h index 1304c80d2f4..dae298fee64 100644 --- a/src/mon/AuthMonitor.h +++ b/src/mon/AuthMonitor.h @@ -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