From 5f78fc9ba6205b8d8760e783697782acdb7f77d4 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Thu, 17 Sep 2009 16:31:58 -0700 Subject: [PATCH] auth: add authmon handling --- src/Makefile.am | 7 +- src/auth/Auth.h | 61 +++++++ src/auth/AuthProtocol.h | 1 + src/authtool.cc | 69 ++++++++ src/ceph.cc | 23 +++ src/include/AuthLibrary.h | 111 ++++++++++++ src/include/ClassLibrary.h | 14 +- src/messages/MAuthMon.h | 88 +++++++++ src/messages/MAuthMonAck.h | 51 ++++++ src/mon/AuthMonitor.cc | 353 +++++++++++++++++++++++++++++++++++++ src/mon/AuthMonitor.h | 72 ++++++++ src/mon/ClassMonitor.cc | 16 +- src/mon/Monitor.cc | 8 +- src/mon/Monitor.h | 1 + src/mon/mon_types.h | 4 +- src/msg/Message.h | 7 +- 16 files changed, 865 insertions(+), 21 deletions(-) create mode 100644 src/authtool.cc create mode 100644 src/include/AuthLibrary.h create mode 100644 src/messages/MAuthMon.h create mode 100644 src/messages/MAuthMonAck.h create mode 100644 src/mon/AuthMonitor.cc create mode 100644 src/mon/AuthMonitor.h diff --git a/src/Makefile.am b/src/Makefile.am index e8017b2f4f9bc..3f07de4f9a3f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -31,7 +31,9 @@ mkmonfs_SOURCES = mkmonfs.cc mkmonfs_LDADD = libmon.a libcrush.a libcommon.a -lcrypto cconf_SOURCES = cconf.cc cconf_LDADD = libcommon.a -lcrypto -bin_PROGRAMS += ceph mkmonfs cconf +authtool_SOURCES = authtool.cc +authtool_LDADD = libcommon.a -lcrypto +bin_PROGRAMS += ceph mkmonfs cconf authtool monmaptool_SOURCES = monmaptool.cc monmaptool_LDADD = libcommon.a -lcrypto @@ -329,6 +331,7 @@ libmon_a_SOURCES = \ mon/PGMonitor.cc \ mon/LogMonitor.cc \ mon/ClassMonitor.cc \ + mon/AuthMonitor.cc \ mon/Elector.cc \ mon/MonitorStore.cc @@ -717,7 +720,7 @@ noinst_HEADERS = \ radosgw/rgw_user.h\ sample.ceph.conf -all_sources = $(cmon_SOURCES) $(ceph_SOURCES) $(mkmonfs_SOURCES) $(monmaptool_SOURCES) \ +all_sources = $(cmon_SOURCES) $(ceph_SOURCES) $(mkmonfs_SOURCES) $(authtool_SOURCES) $(monmaptool_SOURCES) \ $(crushtool_SOURCES) $(osdmaptool_SOURCES) $(cconf_SOURCES) $(mount_ceph_SOURCES) $(cmds_SOURCES) \ $(dumpjournal_SOURCES) $(cosd_SOURCES) $(dupstore_SOURCES) $(streamtest_SOURCES) $(csyn_SOURCES) \ $(testmsgr_SOURCES) $(cfuse_SOURCES) $(fakefuse_SOURCES) $(psim_SOURCES) \ diff --git a/src/auth/Auth.h b/src/auth/Auth.h index 8ae579304f1de..660c6ac40a8ed 100644 --- a/src/auth/Auth.h +++ b/src/auth/Auth.h @@ -16,6 +16,7 @@ #define __AUTHTYPES_H #include "Crypto.h" +#include "AuthProtocol.h" #include "msg/msg_types.h" class Cond; @@ -39,6 +40,66 @@ struct EntityName { ::decode(entity_type, bl); ::decode(name, bl); } + + void to_str(string& str) const { + switch (entity_type) { + case CEPHX_PRINCIPAL_AUTH: + str = "auth"; + break; + case CEPHX_PRINCIPAL_MON: + str = "mon"; + break; + case CEPHX_PRINCIPAL_OSD: + str = "osd"; + break; + case CEPHX_PRINCIPAL_MDS: + str = "mds"; + break; + case CEPHX_PRINCIPAL_CLIENT: + str = "client"; + break; + default: + str = "???"; + break; + } + str.append("."); + str.append(name); + } + string to_str() const { + string s; + to_str(s); + return s; + } + + bool from_str(string& s) { + int pos = s.find('.'); + + if (pos < 0) + return false; + if (pos >= (int)s.size()) + return false; + + string pre = s.substr(0, pos); + const char *pres = pre.c_str(); + + if (strcmp(pres, "auth") == 0) { + entity_type = CEPHX_PRINCIPAL_AUTH; + } else if (strcmp(pres, "mon") == 0) { + entity_type = CEPHX_PRINCIPAL_MON; + } else if (strcmp(pres, "osd") == 0) { + entity_type = CEPHX_PRINCIPAL_OSD; + } else if (strcmp(pres, "mds") == 0) { + entity_type = CEPHX_PRINCIPAL_MDS; + } else if (strcmp(pres, "client") == 0) { + entity_type = CEPHX_PRINCIPAL_CLIENT; + } else { + return false; + } + + name = s.substr(pos); + + return true; + } }; WRITE_CLASS_ENCODER(EntityName); diff --git a/src/auth/AuthProtocol.h b/src/auth/AuthProtocol.h index 25d60e5286703..2067d87dc055b 100644 --- a/src/auth/AuthProtocol.h +++ b/src/auth/AuthProtocol.h @@ -176,6 +176,7 @@ WRITE_CLASS_ENCODER(CephXEnvRequest2); #define CEPHX_PRINCIPAL_MON 0x0002 #define CEPHX_PRINCIPAL_OSD 0x0004 #define CEPHX_PRINCIPAL_MDS 0x0008 +#define CEPHX_PRINCIPAL_CLIENT 0x0010 #define CEPHX_PRINCIPAL_TYPE_MASK 0x00FF diff --git a/src/authtool.cc b/src/authtool.cc new file mode 100644 index 0000000000000..ab7592b00dc48 --- /dev/null +++ b/src/authtool.cc @@ -0,0 +1,69 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2009 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +using namespace std; + +#include "config.h" + +#include "common/common_init.h" +#include "auth/Crypto.h" + +void usage() +{ + cout << " usage: [--gen-key] " << std::endl; + exit(1); +} + + + + +int main(int argc, const char **argv) +{ + vector args; + argv_to_vec(argc, argv, args); + env_to_vec(args); + DEFINE_CONF_VARS(usage); + common_init(args, "osdmaptool", false); + + const char *me = argv[0]; + + const char *fn = 0; + bool gen_key = false; + + FOR_EACH_ARG(args) { + if (CONF_ARG_EQ("gen-key", 'g')) { + CONF_SAFE_SET_ARG_VAL(&gen_key, OPT_BOOL); + } else if (!fn) { + fn = args[i]; + } else + usage(); + } + if (!fn) { + cerr << me << ": must specify filename" << std::endl; + usage(); + } + + CryptoKey key; + key.create(CEPH_SECRET_AES); + + bufferlist bl; + ::encode(key, bl); + int r = bl.write_file(fn); + + if (r < 0) { + cerr << "could not write " << fn << std::endl; + } + + return 0; +} diff --git a/src/ceph.cc b/src/ceph.cc index f336a2a16a0cf..f2b3560e01e11 100644 --- a/src/ceph.cc +++ b/src/ceph.cc @@ -72,6 +72,7 @@ Context *resend_event = 0; #include "mds/MDSMap.h" #include "include/LogEntry.h" #include "include/ClassLibrary.h" +#include "include/AuthLibrary.h" #include "mon/mon_types.h" @@ -199,6 +200,28 @@ void handle_notify(MMonObserveNotify *notify) } break; } + + case PAXOS_AUTH: + { + bufferlist::iterator p = notify->bl.begin(); + if (notify->is_latest) { + AuthLibrary list; + ::decode(list, p); + // show the first class info + map::iterator mapiter = list.library_map.begin(); + if (mapiter != list.library_map.end()) { + dout(0) << " auth " << mapiter->first.to_str() << dendl; + } + } else { + AuthLibEntry entry; + + while (!p.end()) { + entry.decode(p); + dout(0) << " auth " << entry.name.to_str() << dendl; + } + } + break; + } } map_ver[notify->machine_id] = notify->ver; diff --git a/src/include/AuthLibrary.h b/src/include/AuthLibrary.h new file mode 100644 index 0000000000000..a5123ed5bb587 --- /dev/null +++ b/src/include/AuthLibrary.h @@ -0,0 +1,111 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __AUTHLIBRARY_H +#define __AUTHLIBRARY_H + +#include "include/types.h" +#include "include/encoding.h" +#include "auth/Auth.h" + +struct AuthLibEntry { + EntityName name; + CryptoKey secret; + + void encode(bufferlist& bl) const { + ::encode(name, bl); + ::encode(secret, bl); + } + void decode(bufferlist::iterator& bl) { + ::decode(name, bl); + ::decode(secret, bl); + } +}; +WRITE_CLASS_ENCODER(AuthLibEntry) + +typedef enum { + AUTH_INC_NOP, + AUTH_INC_ADD, + AUTH_INC_DEL, + AUTH_INC_ACTIVATE, +} AuthLibIncOp; + +struct AuthLibIncremental { + AuthLibIncOp op; + bufferlist info; + + void encode(bufferlist& bl) const { + __u32 _op = (__u32)op; + ::encode(_op, bl); + ::encode(info, bl); + } + void decode(bufferlist::iterator& bl) { + __u32 _op; + ::decode(_op, bl); + op = (AuthLibIncOp)_op; + assert( op >= AUTH_INC_NOP && op <= AUTH_INC_ACTIVATE); + ::decode(info, bl); + } + + void decode_entry(AuthLibEntry& e) { + bufferlist::iterator iter = info.begin(); + ::decode(e, iter); + } +}; +WRITE_CLASS_ENCODER(AuthLibIncremental) + +struct AuthLibrary { + version_t version; + map library_map; + + AuthLibrary() : version(0) {} + + void add(const EntityName& name, CryptoKey& secret) { + AuthLibEntry entry; + entry.name = name; + entry.secret = secret; + add(entry); + } + + void add(AuthLibEntry& entry) { + library_map[entry.name] = entry; + } + + void remove(const EntityName& name) { + map::iterator mapiter = library_map.find(name); + if (mapiter == library_map.end()) + return; + library_map.erase(mapiter); + } + + bool contains(EntityName& name) { + return (library_map.find(name) != library_map.end()); + } + void encode(bufferlist& bl) const { + ::encode(version, bl); + ::encode(library_map, bl); + } + void decode(bufferlist::iterator& bl) { + ::decode(version, bl); + ::decode(library_map, bl); + } +}; +WRITE_CLASS_ENCODER(AuthLibrary) + +inline ostream& operator<<(ostream& out, const AuthLibEntry& e) +{ + return out << e.name.to_str(); +} + +#endif diff --git a/src/include/ClassLibrary.h b/src/include/ClassLibrary.h index 4433fe78457d6..cfea207d51f4d 100644 --- a/src/include/ClassLibrary.h +++ b/src/include/ClassLibrary.h @@ -12,8 +12,8 @@ * */ -#ifndef __CLASSENTRY_H -#define __CLASSENTRY_H +#ifndef __CLASSLIBRARY_H +#define __CLASSLIBRARY_H #include "include/types.h" #include "include/encoding.h" @@ -56,10 +56,10 @@ struct ClassInfo { WRITE_CLASS_ENCODER(ClassInfo) typedef enum { - INC_NOP, - INC_ADD, - INC_DEL, - INC_ACTIVATE, + CLASS_INC_NOP, + CLASS_INC_ADD, + CLASS_INC_DEL, + CLASS_INC_ACTIVATE, } ClassLibraryIncOp; struct ClassLibraryIncremental { @@ -77,7 +77,7 @@ struct ClassLibraryIncremental { __u32 _op; ::decode(_op, bl); op = (ClassLibraryIncOp)_op; - assert( op >= INC_NOP && op <= INC_ACTIVATE); + assert( op >= CLASS_INC_NOP && op <= CLASS_INC_ACTIVATE); ::decode(info, bl); ::decode(impl, bl); } diff --git a/src/messages/MAuthMon.h b/src/messages/MAuthMon.h new file mode 100644 index 0000000000000..8d54b593d95c0 --- /dev/null +++ b/src/messages/MAuthMon.h @@ -0,0 +1,88 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __MAUTH_H +#define __MAUTH_H + +#include "include/AuthLibrary.h" +#include "messages/PaxosServiceMessage.h" + +enum { + AUTH_NOOP = 0, + AUTH_GET, + AUTH_SET, + AUTH_RESPONSE, +}; + +class MAuthMon : public PaxosServiceMessage { +public: + ceph_fsid_t fsid; + deque info; + deque add; + version_t last; + __s32 action; + + + MAuthMon() : PaxosServiceMessage(MSG_AUTHMON, 0) {} + MAuthMon(const ceph_fsid_t& f, version_t l) : PaxosServiceMessage(MSG_AUTHMON, 0), fsid(f), last(l) {} + MAuthMon(const ceph_fsid_t& f, version_t l, version_t paxos_version) : + PaxosServiceMessage(MSG_AUTHMON, paxos_version), fsid(f), last(l) {} + + const char *get_type_name() { return "class"; } + void print(ostream& out) { + out << "class("; + switch (action) { + case AUTH_NOOP: + out << "NOOP, "; + break; + case AUTH_GET: + out << "GET, "; + break; + case AUTH_SET: + out << "SET, "; + break; + case AUTH_RESPONSE: + out << "SET, "; + break; + default: + out << "Unknown op, "; + break; + } + if (info.size()) + out << info.size() << " entries"; + if (last) + out << "last " << last; + out << ")"; + } + + void encode_payload() { + paxos_encode(); + ::encode(fsid, payload); + ::encode(info, payload); + ::encode(add, payload); + ::encode(last, payload); + ::encode(action, payload); + } + void decode_payload() { + bufferlist::iterator p = payload.begin(); + paxos_decode(p); + ::decode(fsid, p); + ::decode(info, p); + ::decode(add, p); + ::decode(last, p); + ::decode(action, p); + } +}; + +#endif diff --git a/src/messages/MAuthMonAck.h b/src/messages/MAuthMonAck.h new file mode 100644 index 0000000000000..6e38430bcbb2e --- /dev/null +++ b/src/messages/MAuthMonAck.h @@ -0,0 +1,51 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __MAUTHMONACK_H +#define __MHAUTHMONACK_H + +#include "include/AuthLibrary.h" + +class MAuthMonAck : public PaxosServiceMessage { +public: + ceph_fsid_t fsid; + version_t last; + + MAuthMonAck() : PaxosServiceMessage(MSG_AUTHMON_ACK, 0) {} + MAuthMonAck(ceph_fsid_t& f, version_t l) : PaxosServiceMessage(MSG_AUTHMON_ACK, 0), + fsid(f), last(l) {} + + MAuthMonAck(ceph_fsid_t& f, version_t l, version_t paxos_version) : + PaxosServiceMessage(MSG_AUTHMON_ACK, paxos_version), fsid(f), last(l) {} + + + const char *get_type_name() { return "auth_mon_ack"; } + void print(ostream& out) { + out << "auth_mon(last " << last << ")"; + } + + void encode_payload() { + paxos_encode(); + ::encode(fsid, payload); + ::encode(last, payload); + } + void decode_payload() { + bufferlist::iterator p = payload.begin(); + paxos_decode(p); + ::decode(fsid, p); + ::decode(last, p); + } +}; + +#endif diff --git a/src/mon/AuthMonitor.cc b/src/mon/AuthMonitor.cc new file mode 100644 index 0000000000000..19325199f9403 --- /dev/null +++ b/src/mon/AuthMonitor.cc @@ -0,0 +1,353 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#include "AuthMonitor.h" +#include "Monitor.h" +#include "MonitorStore.h" + +#include "messages/MMonCommand.h" +#include "messages/MAuthMon.h" +#include "messages/MAuthMonAck.h" + +#include "include/AuthLibrary.h" +#include "common/Timer.h" + +#include "osd/osd_types.h" +#include "osd/PG.h" // yuck + +#include "config.h" +#include + +#define DOUT_SUBSYS mon +#undef dout_prefix +#define dout_prefix _prefix(mon, paxos->get_version()) +static ostream& _prefix(Monitor *mon, version_t v) { + return *_dout << dbeginl + << "mon" << mon->whoami + << (mon->is_starting() ? (const char*)"(starting)":(mon->is_leader() ? (const char*)"(leader)":(mon->is_peon() ? (const char*)"(peon)":(const char*)"(?\?)"))) + << ".class v" << v << " "; +} + +ostream& operator<<(ostream& out, AuthMonitor& pm) +{ + std::stringstream ss; + + return out << "auth"; +} + +/* + Tick function to update the map based on performance every N seconds +*/ + +void AuthMonitor::tick() +{ + if (!paxos->is_active()) return; + + update_from_paxos(); + dout(10) << *this << dendl; + + if (!mon->is_leader()) return; + +} + +void AuthMonitor::create_initial(bufferlist& bl) +{ + dout(0) << "create_initial -- creating initial map" << dendl; + AuthLibEntry l; + AuthLibIncremental inc; + ::encode(l, inc.info); + inc.op = AUTH_INC_NOP; + pending_auth.push_back(inc); +} + +bool AuthMonitor::store_entry(AuthLibEntry& entry) +{ + string entry_str; + + entry.name.to_str(entry_str); + + + bufferlist bl; + ::encode(entry, bl); + mon->store->put_bl_ss(bl, "auth_lib", entry_str.c_str()); + dout(0) << "adding name=" << entry_str << dendl; + + return true; +} + + +bool AuthMonitor::update_from_paxos() +{ + version_t paxosv = paxos->get_version(); + if (paxosv == list.version) return true; + assert(paxosv >= list.version); + + bufferlist blog; + + if (list.version == 0 && paxosv > 1) { + // startup: just load latest full map + bufferlist latest; + version_t v = paxos->get_latest(latest); + if (v) { + dout(7) << "update_from_paxos startup: loading summary e" << v << dendl; + bufferlist::iterator p = latest.begin(); + ::decode(list, p); + } + } + + // walk through incrementals + while (paxosv > list.version) { + bufferlist bl; + bool success = paxos->read(list.version+1, bl); + assert(success); + + bufferlist::iterator p = bl.begin(); + AuthLibIncremental inc; + ::decode(inc, p); + AuthLibEntry entry; + inc.decode_entry(entry); + switch (inc.op) { + case AUTH_INC_ADD: + list.add(entry); + break; + case AUTH_INC_DEL: + list.remove(entry.name); + break; + case AUTH_INC_NOP: + break; + default: + assert(0); + } + + list.version++; + } + + bufferlist bl; + ::encode(list, bl); + paxos->stash_latest(paxosv, bl); + + return true; +} + +void AuthMonitor::create_pending() +{ + pending_auth.clear(); + pending_list = list; + dout(10) << "create_pending v " << (paxos->get_version() + 1) << dendl; +} + +void AuthMonitor::encode_pending(bufferlist &bl) +{ + dout(10) << "encode_pending v " << (paxos->get_version() + 1) << dendl; + for (vector::iterator p = pending_auth.begin(); + p != pending_auth.end(); + p++) + p->encode(bl); +} + +bool AuthMonitor::preprocess_query(PaxosServiceMessage *m) +{ + dout(10) << "preprocess_query " << *m << " from " << m->get_orig_source_inst() << dendl; + switch (m->get_type()) { + case MSG_MON_COMMAND: + return preprocess_command((MMonCommand*)m); + + case MSG_AUTHMON: + return preprocess_auth((MAuthMon*)m); + + default: + assert(0); + delete m; + return true; + } +} + +bool AuthMonitor::prepare_update(PaxosServiceMessage *m) +{ + dout(10) << "prepare_update " << *m << " from " << m->get_orig_source_inst() << dendl; + switch (m->get_type()) { + case MSG_MON_COMMAND: + return prepare_command((MMonCommand*)m); + case MSG_AUTHMON: + return prepare_auth((MAuthMon*)m); + default: + assert(0); + delete m; + return false; + } +} + +void AuthMonitor::committed() +{ + +} + +bool AuthMonitor::preprocess_auth(MAuthMon *m) +{ + dout(10) << "preprocess_auth " << *m << " from " << m->get_orig_source() << dendl; + + int num_new = 0; + for (deque::iterator p = m->info.begin(); + p != m->info.end(); + p++) { + if (!pending_list.contains((*p).name)) + num_new++; + } + if (!num_new) { + dout(10) << " nothing new" << dendl; + return true; + } + return false; +} + +bool AuthMonitor::prepare_auth(MAuthMon *m) +{ + dout(10) << "prepare_auth " << *m << " from " << m->get_orig_source() << dendl; + + if (ceph_fsid_compare(&m->fsid, &mon->monmap->fsid)) { + dout(0) << "handle_auth on fsid " << m->fsid << " != " << mon->monmap->fsid << dendl; + delete m; + return false; + } + for (deque::iterator p = m->info.begin(); + p != m->info.end(); p++) { + dout(10) << " writing auth " << *p << dendl; + if (!pending_list.contains((*p).name)) { + AuthLibIncremental inc; + ::encode(*p, inc.info); + pending_list.add(*p); + pending_auth.push_back(inc); + } + } + + paxos->wait_for_commit(new C_Auth(this, m, m->get_orig_source_inst())); + return true; +} + +void AuthMonitor::_updated_auth(MAuthMon *m, entity_inst_t who) +{ + dout(7) << "_updated_auth for " << who << dendl; + mon->messenger->send_message(new MAuthMonAck(m->fsid, m->last), who); + delete m; +} + +void AuthMonitor::auth_usage(stringstream& ss) +{ + ss << "error: usage:" << std::endl; + ss << " auth <--in-file=filename>" << std::endl; + ss << " auth " << std::endl; +} + +bool AuthMonitor::preprocess_command(MMonCommand *m) +{ + int r = -1; + bufferlist rdata; + stringstream ss; + + if (m->cmd.size() > 1) { + if (m->cmd[1] == "add" || + m->cmd[1] == "del" || + m->cmd[1] == "activate" || + m->cmd[1] == "list") { + return false; + } + } + + auth_usage(ss); + r = -EINVAL; + + string rs; + getline(ss, rs, '\0'); + mon->reply_command(m, r, rs, rdata, paxos->get_version()); + return true; +} + + +bool AuthMonitor::prepare_command(MMonCommand *m) +{ + stringstream ss; + string rs; + int err = -EINVAL; + + // nothing here yet + if (m->cmd.size() > 1) { + if (m->cmd[1] == "add" && m->cmd.size() >= 3) { + string entity_name = m->cmd[2]; + + AuthLibEntry entry; + entry.name.from_str(entity_name); + + bufferlist bl = m->get_data(); + bufferlist::iterator iter = bl.begin(); + ::decode(entry.secret, iter); + + AuthLibIncremental inc; + dout(0) << "storing auth for " << entity_name << dendl; + ::encode(entry, inc.info); + inc.op = AUTH_INC_ADD; + pending_list.add(entry); + pending_auth.push_back(inc); + ss << "updated"; + getline(ss, rs); + paxos->wait_for_commit(new Monitor::C_Command(mon, m, 0, rs, paxos->get_version())); + return true; + } else if (m->cmd[1] == "del" && m->cmd.size() >= 5) { + string name = m->cmd[2]; + AuthLibEntry entry; + entry.name.from_str(name); + map::iterator iter = list.library_map.find(entry.name); + if (iter == list.library_map.end()) { + ss << "couldn't find entry " << name; + rs = -ENOENT; + goto done; + } + AuthLibIncremental inc; + ::encode(entry, inc.info); + inc.op = AUTH_INC_DEL; + pending_list.add(entry); + pending_auth.push_back(inc); + + ss << "updated"; + getline(ss, rs); + paxos->wait_for_commit(new Monitor::C_Command(mon, m, 0, rs, paxos->get_version())); + return true; + } else if (m->cmd[1] == "list") { + map::iterator mapiter = list.library_map.begin(); + if (mapiter != list.library_map.end()) { + ss << "installed auth entries: " << std::endl; + + while (mapiter != list.library_map.end()) { + AuthLibEntry& entry = mapiter->second; + ss << entry.name.to_str() << std::endl; + + ++mapiter; + } + } else { + ss << "no installed auth entries!"; + } + err = 0; + goto done; + } else { + auth_usage(ss); + } + } else { + auth_usage(ss); + } + +done: + getline(ss, rs, '\0'); + mon->reply_command(m, err, rs, paxos->get_version()); + return false; +} diff --git a/src/mon/AuthMonitor.h b/src/mon/AuthMonitor.h new file mode 100644 index 0000000000000..2517dda2381e4 --- /dev/null +++ b/src/mon/AuthMonitor.h @@ -0,0 +1,72 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef __AUTHMONITOR_H +#define __AUTHMONITOR_H + +#include +#include +using namespace std; + +#include "include/types.h" +#include "msg/Messenger.h" +#include "PaxosService.h" +#include "mon/Monitor.h" + +#include "include/AuthLibrary.h" + +class MMonCommand; +class MAuthMon; + +class AuthMonitor : public PaxosService { + void auth_usage(stringstream& ss); +private: + vector pending_auth; + AuthLibrary pending_list, list; + + void create_initial(bufferlist& bl); + bool update_from_paxos(); + void create_pending(); // prepare a new pending + void encode_pending(bufferlist &bl); // propose pending update to peers + + void committed(); + + bool preprocess_query(PaxosServiceMessage *m); // true if processed. + bool prepare_update(PaxosServiceMessage *m); + + bool preprocess_auth(MAuthMon *m); + bool prepare_auth(MAuthMon *m); + void _updated_auth(MAuthMon *m, entity_inst_t who); + + struct C_Auth : public Context { + AuthMonitor *authmon; + MAuthMon *ack; + entity_inst_t who; + C_Auth(AuthMonitor *p, MAuthMon *a, entity_inst_t w) : authmon(p), ack(a), who(w) {} + void finish(int r) { + authmon->_updated_auth(ack, who); + } + }; + + bool preprocess_command(MMonCommand *m); + bool prepare_command(MMonCommand *m); + bool store_entry(AuthLibEntry& entry); + public: + AuthMonitor(Monitor *mn, Paxos *p) : PaxosService(mn, p) { } + void handle_request(MAuthMon *m); + + void tick(); // check state, take actions +}; + +#endif diff --git a/src/mon/ClassMonitor.cc b/src/mon/ClassMonitor.cc index e092055498a97..fda534b1d8147 100644 --- a/src/mon/ClassMonitor.cc +++ b/src/mon/ClassMonitor.cc @@ -71,7 +71,7 @@ void ClassMonitor::create_initial(bufferlist& bl) ClassLibraryIncremental inc; ::encode(i, inc.impl); ::encode(l, inc.info); - inc.op = INC_NOP; + inc.op = CLASS_INC_NOP; pending_class.insert(pair(i.stamp, inc)); } @@ -124,17 +124,17 @@ bool ClassMonitor::update_from_paxos() ClassInfo info; inc.decode_info(info); switch (inc.op) { - case INC_ADD: + case CLASS_INC_ADD: inc.decode_impl(impl); if (impl.binary.length() > 0) { store_impl(info, impl); list.add(info.name, info.version); } break; - case INC_DEL: + case CLASS_INC_DEL: list.remove(info.name, info.version); break; - case INC_ACTIVATE: + case CLASS_INC_ACTIVATE: { map::iterator mapiter = list.library_map.find(info.name); if (mapiter == list.library_map.end()) { @@ -144,7 +144,7 @@ bool ClassMonitor::update_from_paxos() } } break; - case INC_NOP: + case CLASS_INC_NOP: break; default: assert(0); @@ -332,7 +332,7 @@ bool ClassMonitor::prepare_command(MMonCommand *m) dout(0) << "storing class " << name << " v" << info.version << dendl; ::encode(impl, inc.impl); ::encode(info, inc.info); - inc.op = INC_ADD; + inc.op = CLASS_INC_ADD; pending_list.add(info); pending_class.insert(pair(impl.stamp, inc)); ss << "updated"; @@ -362,7 +362,7 @@ bool ClassMonitor::prepare_command(MMonCommand *m) ClassImpl impl; impl.stamp = g_clock.now(); ::encode(*info, inc.info); - inc.op = INC_DEL; + inc.op = CLASS_INC_DEL; pending_list.add(*info); pending_class.insert(pair(impl.stamp, inc)); @@ -388,7 +388,7 @@ bool ClassMonitor::prepare_command(MMonCommand *m) ClassImpl impl; impl.stamp = g_clock.now(); ::encode(info, inc.info); - inc.op = INC_ACTIVATE; + inc.op = CLASS_INC_ACTIVATE; pending_list.add(info); pending_class.insert(pair(impl.stamp, inc)); ss << "updated"; diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index 57935c329327f..b89253c1826e3 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -49,6 +49,7 @@ #include "PGMonitor.h" #include "LogMonitor.h" #include "ClassMonitor.h" +#include "AuthMonitor.h" #include "osd/OSDMap.h" @@ -93,6 +94,7 @@ Monitor::Monitor(int w, MonitorStore *s, Messenger *m, MonMap *map) : paxos_service[PAXOS_PGMAP] = new PGMonitor(this, add_paxos(PAXOS_PGMAP)); paxos_service[PAXOS_LOG] = new LogMonitor(this, add_paxos(PAXOS_LOG)); paxos_service[PAXOS_CLASS] = new ClassMonitor(this, add_paxos(PAXOS_CLASS)); + paxos_service[PAXOS_AUTH] = new AuthMonitor(this, add_paxos(PAXOS_AUTH)); } Paxos *Monitor::add_paxos(int type) @@ -270,7 +272,11 @@ void Monitor::handle_command(MMonCommand *m) classmon()->dispatch(m); return; } - if (m->cmd[0] == "mon") { + if (m->cmd[0] == "auth") { + authmon()->dispatch(m); + return; + } + if (m->cmd[0] == "mon") { if (m->cmd[1] == "injectargs" && m->cmd.size() == 4) { vector args(2); args[0] = "_injectargs"; diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h index 09d26ffd0b60d..bb9c9f5db452c 100644 --- a/src/mon/Monitor.h +++ b/src/mon/Monitor.h @@ -118,6 +118,7 @@ public: class OSDMonitor *osdmon() { return (class OSDMonitor *)paxos_service[PAXOS_OSDMAP]; } class ClientMonitor *clientmon() { return (class ClientMonitor *)paxos_service[PAXOS_CLIENTMAP]; } class ClassMonitor *classmon() { return (class ClassMonitor *)paxos_service[PAXOS_CLASS]; } + class AuthMonitor *authmon() { return (class AuthMonitor *)paxos_service[PAXOS_AUTH]; } friend class Paxos; friend class OSDMonitor; diff --git a/src/mon/mon_types.h b/src/mon/mon_types.h index 0bb6e71e80deb..9441bb5e28db7 100644 --- a/src/mon/mon_types.h +++ b/src/mon/mon_types.h @@ -21,7 +21,8 @@ #define PAXOS_CLIENTMAP 3 #define PAXOS_LOG 4 #define PAXOS_CLASS 5 -#define PAXOS_NUM 6 +#define PAXOS_AUTH 6 +#define PAXOS_NUM 7 inline const char *get_paxos_name(int p) { switch (p) { @@ -31,6 +32,7 @@ inline const char *get_paxos_name(int p) { case PAXOS_PGMAP: return "pgmap"; case PAXOS_LOG: return "logm"; case PAXOS_CLASS: return "class"; + case PAXOS_AUTH: return "auth"; default: assert(0); return 0; } } diff --git a/src/msg/Message.h b/src/msg/Message.h index f33c1a75f9fc8..d56234cbdd3e5 100644 --- a/src/msg/Message.h +++ b/src/msg/Message.h @@ -20,8 +20,8 @@ #include "config.h" // monitor internal -#define MSG_MON_ELECTION 60 -#define MSG_MON_PAXOS 61 +#define MSG_MON_ELECTION 65 +#define MSG_MON_PAXOS 66 /* monitor <-> mon admin tool */ #define MSG_MON_COMMAND 50 @@ -36,6 +36,9 @@ #define MSG_GETPOOLSTATS 58 #define MSG_GETPOOLSTATSREPLY 59 +#define MSG_AUTHMON 60 +#define MSG_AUTHMON_ACK 61 + #define MSG_POOLOP 49 #define MSG_POOLOPREPLY 48 -- 2.39.5