::encode(ticket_req, request);
}
-
bool build_service_ticket(SessionAuthInfo& info, bufferlist& reply)
{
AuthServiceTicketInfo ticket_info;
ticket_info.session_key = info.session_key;
ticket_info.ticket = info.ticket;
+ ticket_info.ticket.caps = info.ticket.caps;
::encode(info.secret_id, reply);
- dout(0) << "encoded info.secret_id=" << info.secret_id << dendl;
+ dout(0) << "encoded info.secret_id=" << info.secret_id << " ticket_info.ticket.name=" << ticket_info.ticket.name.to_str() << dendl;
if (info.service_secret.get_secret().length())
hexdump("service_secret", info.service_secret.get_secret().c_str(), info.service_secret.get_secret().length());
if (encode_encrypt(ticket_info, info.service_secret, reply) < 0)
if (secret_id == (uint64_t)-1) {
EntityName name;
name.entity_type = service_id;
- map<string, bufferlist> caps;
- if (!keys.get_secret(name, service_secret, caps)) {
+ if (!keys.get_secret(name, service_secret)) {
dout(0) << "could not get general service secret for service_id=" << service_id << " secret_id=" << secret_id << dendl;
return false;
}
dout(0) << "could not decrypt ticket info" << dendl;
return false;
}
+ dout(0) << "decoded ticket_info.ticket.name=" << ticket_info.ticket.name.to_str() << dendl;
AuthAuthorize auth_msg;
if (decode_decrypt(auth_msg, ticket_info.session_key, indata) < 0) {
#define AUTH_ENC_MAGIC 0xff009cad8826aa55
+struct EntityAuth {
+ CryptoKey key;
+ map<string, bufferlist> caps;
+
+ void encode(bufferlist& bl) const {
+ ::encode(key, bl);
+ ::encode(caps, bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ ::decode(key, bl);
+ ::decode(caps, bl);
+ }
+};
+WRITE_CLASS_ENCODER(EntityAuth)
+
struct AuthContext {
int status;
// int id;
EntityName name;
entity_addr_t addr;
utime_t created, renew_after, expires;
- map<string, bufferlist> caps;
+ bufferlist caps;
__u32 flags;
AuthTicket() : flags(0) {}
CryptoKey session_key;
void encode(bufferlist& bl) const {
- ::encode(ticket.renew_after, bl);
- ::encode(ticket.expires, bl);
+ ::encode(ticket, bl);
::encode(session_key, bl);
}
void decode(bufferlist::iterator& bl) {
- ::decode(ticket.renew_after, bl);
- ::decode(ticket.expires, bl);
+ ::decode(ticket, bl);
::decode(session_key, bl);
}
};
class KeysKeeper {
public:
- virtual bool get_secret(EntityName& name, CryptoKey& secret, map<string, bufferlist>& caps) = 0;
+ virtual bool get_secret(EntityName& name, CryptoKey& secret) = 0;
virtual bool get_service_secret(uint32_t service_id, uint64_t secret_id, CryptoKey& secret) = 0;
};
class Monitor;
+static inline void get_entity_type_str(uint32_t entity_type,string& s) {
+ switch (entity_type) {
+ case CEPHX_PRINCIPAL_AUTH:
+ s = "auth";
+ break;
+ case CEPHX_PRINCIPAL_MON:
+ s = "mon";
+ break;
+ case CEPHX_PRINCIPAL_OSD:
+ s = "osd";
+ break;
+ case CEPHX_PRINCIPAL_MDS:
+ s = "mds";
+ break;
+ case CEPHX_PRINCIPAL_CLIENT:
+ s = "client";
+ break;
+ default:
+ s = "???";
+ break;
+ }
+}
+
static inline uint32_t peer_id_to_entity_type(int peer_id)
{
switch (peer_id) {
}
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;
- }
+ get_entity_type_str(entity_type, str);
str.append(".");
str.append(name);
}
set_type(type);
name = id;
}
+
+ void get_type_str(string& s) {
+ get_entity_type_str(entity_type, s);
+ }
};
WRITE_CLASS_ENCODER(EntityName);
::decode(req, indata);
CryptoKey secret;
- map<string,bufferlist> caps;
dout(0) << "entity_name=" << entity_name.to_str() << dendl;
- if (!mon->keys_server.get_secret(entity_name, secret, caps)) {
+ if (!mon->keys_server.get_secret(entity_name, secret)) {
dout(0) << "couldn't find entity name: " << entity_name.to_str() << dendl;
ret = -EPERM;
break;
SessionAuthInfo info;
CryptoKey principal_secret;
- if (mon->keys_server.get_secret(req.name, principal_secret, info.ticket.caps) < 0) {
+ if (mon->keys_server.get_secret(req.name, principal_secret) < 0) {
ret = -EPERM;
break;
}
break;
}
+ ret = 0;
vector<SessionAuthInfo> info_vec;
for (uint32_t service_id = 1; service_id != (CEPHX_PRINCIPAL_TYPE_MASK + 1); service_id <<= 1) {
if (ticket_req.keys & service_id) {
info_vec.push_back(info);
}
}
-
build_cephx_response_header(request_type, ret, result_bl);
build_service_ticket_reply(auth_ticket_info.session_key, info_vec, result_bl);
- ret = 0;
}
break;
default:
switch (request_type) {
case CEPHX_OPEN_SESSION:
{
- dout(0) << "CEPHX_OPEN_SESSION " << cephx_header.request_type << dendl;
+ dout(0) << "CEPHX_OPEN_SESSION " << cephx_header.request_type << dendl;
- ret = 0;
bufferlist tmp_bl;
- AuthServiceTicketInfo auth_ticket_info;
- if (!::verify_authorizer(*keys, indata, auth_ticket_info, tmp_bl)) {
- dout(0) << "could not verify authorizer" << dendl;
- ret = -EPERM;
- }
+ ret = verify_authorizer(0, indata, tmp_bl);
result_bl.claim_append(tmp_bl);
}
break;
dout(0) << "could not verify authorizer" << dendl;
ret = -EPERM;
}
+ dout(0) << "caps len=" << auth_ticket_info.ticket.caps.length() << dendl;
+ if (auth_ticket_info.ticket.caps.length()) {
+ string caps;
+ bufferlist::iterator iter = auth_ticket_info.ticket.caps.begin();
+ ::decode(caps, iter);
+ dout(0) << "got caps: " << caps << dendl;
+ }
} catch (buffer::error *err) {
ret = -EINVAL;
}
int total_out = 0;
int outlen;
#define OUT_BUF_EXTRA 128
- unsigned char outbuf[outlen + OUT_BUF_EXTRA];
+ unsigned char outbuf[max_out + OUT_BUF_EXTRA];
dout(0) << "secret.length=" << secret.length() << dendl;
bufferlist::iterator iter = bl.begin();
- map<string, CryptoKey> m;
- map<string, CryptoKey>::iterator miter;
+ map<string, EntityAuth> m;
+ map<string, EntityAuth>::iterator miter;
::decode(m, iter);
if (miter == m.end())
return false;
}
- master = miter->second;
+ master = miter->second.key;
return true;
}
bool need_rotating_secrets();
- bool get_secret(EntityName& name, CryptoKey& secret, map<string, bufferlist>& caps) {
+ bool get_secret(EntityName& name, CryptoKey& secret) {
get_master(secret);
return true;
}
return true;
}
-bool KeysServerData::get_secret(EntityName& name, CryptoKey& secret, map<string,bufferlist>& caps)
+bool KeysServerData::get_secret(EntityName& name, CryptoKey& secret)
{
- map<EntityName, CryptoKey>::iterator iter = secrets.find(name);
+ map<EntityName, EntityAuth>::iterator iter = secrets.find(name);
if (iter == secrets.end())
return false;
- secret = iter->second;
+ secret = iter->second.key;
+
+ return true;
+}
+
+bool KeysServerData::get_caps(EntityName& name, string& type, bufferlist& caps)
+{
+ dout(0) << "get_caps: name=" << name.to_str() << dendl;
+ map<EntityName, EntityAuth>::iterator iter = secrets.find(name);
+ if (iter == secrets.end())
+ return false;
+
+ dout(0) << "get_secret: num of caps=" << iter->second.caps.size() << dendl;
+ map<string, bufferlist>::iterator capsiter = iter->second.caps.find(type);
+ if (capsiter != iter->second.caps.end()) {
+ caps = capsiter->second;
+ }
return true;
}
return false;
}
-bool KeysServer::get_secret(EntityName& name, CryptoKey& secret, map<string,bufferlist>& caps)
+bool KeysServer::get_secret(EntityName& name, CryptoKey& secret)
{
Mutex::Locker l(lock);
- return data.get_secret(name, secret, caps);
+ return data.get_secret(name, secret);
+}
+
+bool KeysServer::get_caps(EntityName& name, string& type, bufferlist& caps)
+{
+ Mutex::Locker l(lock);
+
+ return data.get_caps(name, type, caps);
}
bool KeysServer::get_service_secret(uint32_t service_id, ExpiringCryptoKey& secret, uint64_t& secret_id)
Mutex::Locker l(lock);
- data.add_secret(name, secret);
+ EntityAuth auth;
+ auth.key = secret;
+
+ data.add_auth(name, auth);
return true;
}
{
Mutex::Locker l(lock);
- map<EntityName, CryptoKey>::iterator mapiter = data.secrets_begin();
+ map<EntityName, EntityAuth>::iterator mapiter = data.secrets_begin();
if (mapiter != data.secrets_end()) {
ss << "installed auth entries: " << std::endl;
while (mapiter != data.secrets_end()) {
const EntityName& name = mapiter->first;
ss << name.to_str() << std::endl;
-
+
+ map<string, bufferlist>::iterator capsiter = mapiter->second.caps.begin();
+ for (; capsiter != mapiter->second.caps.end(); ++capsiter) {
+ bufferlist::iterator dataiter = capsiter->second.begin();
+ string caps;
+ ::decode(caps, dataiter);
+ ss << "\tcaps: [" << capsiter->first << "] " << caps << std::endl;
+ }
+
++mapiter;
}
} else {
{
Mutex::Locker l(lock);
- map<EntityName, CryptoKey>::iterator mapiter = data.find_name(name);
+ map<EntityName, EntityAuth>::iterator mapiter = data.find_name(name);
if (mapiter == data.secrets_end())
return false;
- CryptoKey& specific_key = mapiter->second;
+ CryptoKey& specific_key = mapiter->second.key;
map<uint32_t, RotatingSecrets>::iterator rotate_iter = data.rotating_secrets.find(name.entity_type);
if (rotate_iter == data.rotating_secrets.end())
generate_secret(info.session_key);
info.service_id = service_id;
-
- info.ticket.caps = auth_ticket_info.ticket.caps;
+
+ string s;
+ get_entity_type_str(service_id, s);
+
+ if (!data.get_caps(info.ticket.name, s, info.ticket.caps)) {
+ return -EINVAL;
+ }
return 0;
}
return -EPERM;
}
+ Mutex::Locker l(lock);
+
return _build_session_auth_info(service_id, auth_ticket_info, info);
}
utime_t next_rotating_time;
/* for each entity */
- map<EntityName, CryptoKey> secrets;
+ map<EntityName, EntityAuth> secrets;
/* for each service type */
map<uint32_t, RotatingSecrets> rotating_secrets;
return (secrets.find(name) != secrets.end());
}
- void add_secret(const EntityName& name, CryptoKey& secret) {
- secrets[name] = secret;
+ void add_auth(const EntityName& name, EntityAuth& auth) {
+ secrets[name] = auth;
}
void remove_secret(const EntityName& name) {
- map<EntityName, CryptoKey>::iterator iter = secrets.find(name);
+ map<EntityName, EntityAuth>::iterator iter = secrets.find(name);
if (iter == secrets.end())
return;
secrets.erase(iter);
bool get_service_secret(uint32_t service_id, ExpiringCryptoKey& secret, uint64_t& secret_id);
bool get_service_secret(uint32_t service_id, CryptoKey& secret, uint64_t& secret_id);
bool get_service_secret(uint32_t service_id, uint64_t secret_id, CryptoKey& secret);
- bool get_secret(EntityName& name, CryptoKey& secret, map<string,bufferlist>& caps);
+ bool get_secret(EntityName& name, CryptoKey& secret);
+ bool get_caps(EntityName& name, string& type, bufferlist& caps);
- map<EntityName, CryptoKey>::iterator secrets_begin() { return secrets.begin(); }
- map<EntityName, CryptoKey>::iterator secrets_end() { return secrets.end(); }
- map<EntityName, CryptoKey>::iterator find_name(EntityName& name) { return secrets.find(name); }
+ map<EntityName, EntityAuth>::iterator secrets_begin() { return secrets.begin(); }
+ map<EntityName, EntityAuth>::iterator secrets_end() { return secrets.end(); }
+ map<EntityName, EntityAuth>::iterator find_name(EntityName& name) { return secrets.find(name); }
};
WRITE_CLASS_ENCODER(KeysServerData);
bool generate_secret(CryptoKey& secret);
- bool get_secret(EntityName& name, CryptoKey& secret, map<string,bufferlist>& caps);
+ bool get_secret(EntityName& name, CryptoKey& secret);
+ bool get_caps(EntityName& name, string& type, bufferlist& caps);
bool get_active_rotating_secret(EntityName& name, CryptoKey& secret);
int start_server(bool init);
void rotate_timeout(double timeout);
data.version = ver;
}
- void add_secret(const EntityName& name, CryptoKey& secret) {
+ void add_auth(const EntityName& name, EntityAuth& auth) {
Mutex::Locker l(lock);
- data.add_secret(name, secret);
+ data.add_auth(name, auth);
}
void remove_secret(const EntityName& name) {
#include "config.h"
+#include "common/ConfUtils.h"
#include "common/common_init.h"
#include "auth/Crypto.h"
#include "auth/KeysServer.h"
+#include "auth/Auth.h"
void usage()
{
- cout << " usage: [--gen-key] [--name] [--list] <filename>" << std::endl;
+ cout << " usage: [--gen-key] [--name=<name>] [--caps=<filename>] [--list] <filename>" << std::endl;
exit(1);
}
bool gen_key = false;
bool list = false;
const char *name = "";
+ const char *caps_fn = NULL;
FOR_EACH_ARG(args) {
if (CONF_ARG_EQ("gen-key", 'g')) {
CONF_SAFE_SET_ARG_VAL(&name, OPT_STR);
} else if (CONF_ARG_EQ("list", 'l')) {
CONF_SAFE_SET_ARG_VAL(&list, OPT_BOOL);
+ } else if (CONF_ARG_EQ("caps", '\0')) {
+ CONF_SAFE_SET_ARG_VAL(&caps_fn, OPT_STR);
} else if (!fn) {
fn = args[i];
} else
usage();
}
- map<string, CryptoKey> keys_map;
+ map<string, EntityAuth> keys_map;
string s = name;
+
+ if (caps_fn) {
+ if (!name || !(*name)) {
+ cerr << "can't specify caps without name" << std::endl;
+ exit(1);
+ }
+ }
+
CryptoKey key;
key.create(CEPH_SECRET_AES);
}
if (gen_key) {
- keys_map[s] = key;
+ keys_map[s].key = key;
}
if (list) {
- map<string, CryptoKey>::iterator iter = keys_map.begin();
+ map<string, EntityAuth>::iterator iter = keys_map.begin();
for (; iter != keys_map.end(); ++iter) {
string n = iter->first;
if (n.empty()) {
} else {
cout << n << 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;
+ }
+ }
+ }
+
+ 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);
+ }
+ const char *key_names[] = { "mon", "osd", "mds", NULL };
+ for (int i=0; key_names[i]; i++) {
+ char *val;
+ cf->read("global", key_names[i], &val, NULL);
+ if (val) {
+ bufferlist bl;
+ ::encode(val, bl);
+ string s(key_names[i]);
+ caps[s] = bl;
+ free(val);
+ }
}
}
ConfSection(std::string sec_name) : name(sec_name) { }
const std::string& get_name() { return name; }
+ ConfList& get_list() { return conf_list; }
};
typedef std::map<std::string, ConfSection *> SectionMap;
bool rotating;
EntityName name;
- CryptoKey secret;
+ EntityAuth auth;
bufferlist rotating_bl;
::encode(r, bl);
if (!rotating) {
::encode(name, bl);
- ::encode(secret, bl);
+ ::encode(auth, bl);
} else {
::encode(rotating_bl, bl);
}
rotating = (bool)r;
if (!rotating) {
::decode(name, bl);
- ::decode(secret, bl);
+ ::decode(auth, bl);
} else {
::decode(rotating_bl, bl);
}
}
};
WRITE_CLASS_ENCODER(AuthLibIncremental)
-#if 0
-struct AuthLibrary {
- version_t version;
- KeysServerData keys;
-
- AuthLibrary() : version(0) {}
-
- void add_secret(const EntityName& name, CryptoKey& secret) {
- keys.add_secret(name, secret);
- }
-
- void add(AuthLibEntry& entry) {
- if (entry.rotating) {
- keys.add_rotating_secret(entry.service_id, entry.rotating_secret);
- } else {
- add_secret(entry.name, entry.secret);
- }
- }
-
- void remove(const EntityName& name) {
- keys.remove_secret(name);
- }
-
- bool contains(EntityName& name) {
- return keys.contains(name);
- }
- void encode(bufferlist& bl) const {
- ::encode(version, bl);
- ::encode(keys, bl);
- }
- void decode(bufferlist::iterator& bl) {
- ::decode(version, bl);
- ::decode(keys, bl);
- }
-};
-WRITE_CLASS_ENCODER(AuthLibrary)
-#endif
inline ostream& operator<<(ostream& out, const AuthLibEntry& e)
{
{
dout(0) << "create_initial -- creating initial map" << dendl;
if (g_conf.keys_file) {
- map<string, CryptoKey> keys_map;
+ map<string, EntityAuth> keys_map;
dout(0) << "reading initial keys file " << dendl;
bufferlist bl;
int r = bl.read_file(g_conf.keys_file);
cerr << "error reading file " << g_conf.keys_file << std::endl;
}
if (read_ok) {
- map<string, CryptoKey>::iterator iter = keys_map.begin();
+ map<string, EntityAuth>::iterator iter = keys_map.begin();
for (; iter != keys_map.end(); ++iter) {
string n = iter->first;
if (!n.empty()) {
dout(0) << "bad entity name " << n << dendl;
continue;
}
- entry.secret = iter->second;
+ entry.auth = iter->second;
AuthLibIncremental inc;
::encode(entry, inc.info);
case AUTH_INC_ADD:
if (!entry.rotating) {
derr(0) << "got entry name=" << entry.name.to_str() << dendl;
- mon->keys_server.add_secret(entry.name, entry.secret);
+ mon->keys_server.add_auth(entry.name, entry.auth);
} else {
derr(0) << "got AUTH_INC_ADD with entry.rotating" << dendl;
}
bufferlist bl = m->get_data();
dout(0) << "AuthMonitor::prepare_command bl.length()=" << bl.length() << dendl;
bufferlist::iterator iter = bl.begin();
- map<string, CryptoKey> crypto_map;
- map<string, CryptoKey>::iterator miter;
+ map<string, EntityAuth> crypto_map;
+ map<string, EntityAuth>::iterator miter;
try {
::decode(crypto_map, iter);
} catch (buffer::error *err) {
string s = miter->first;
entry.name.from_str(s);
}
- entry.secret = miter->second;
+ entry.auth = miter->second;
::encode(entry, inc.info);
inc.op = AUTH_INC_ADD;
pending_auth.push_back(inc);
name.entity_type = CEPHX_PRINCIPAL_MON;
CryptoKey secret;
- map<string, bufferlist> caps;
- if (!keys_server.get_secret(name, secret, caps)) {
+ if (!keys_server.get_secret(name, secret)) {
dout(0) << "couldn't get secret for mon service!" << dendl;
stringstream ss;
keys_server.list_secrets(ss);
MON_ADDR=""
conf="ceph.conf"
+admin_caps="admin.caps.conf"
+osd_caps="osd.caps.conf"
+mds_caps="mds.caps.conf"
usage="usage: $0 [option]... [mon] [mds] [osd]\n"
usage=$usage"options:\n"
echo
fi
+cat <<EOF > $admin_caps
+; generated by vstart.sh on `date`
+ mon = "allow"
+ osd = "allow"
+ mds = "allow"
+EOF
$SUDO $CEPH_BIN/authtool --gen-key --name=mon. $monkeys_fn
- $SUDO $CEPH_BIN/authtool --gen-key --name=client.admin $monkeys_fn
+ $SUDO $CEPH_BIN/authtool --gen-key --name=client.admin --caps=$admin_caps $monkeys_fn
# build a fresh fs monmap, mon fs
# $CEPH_BIN/monmaptool --create --clobber --print .ceph_monmap
echo $SUDO $CEPH_BIN/cosd -i $osd $ARGS --mkfs # --debug_journal 20 --debug_osd 20 --debug_filestore 20 --debug_ebofs 20
$SUDO $CEPH_BIN/cosd -i $osd $ARGS --mkfs # --debug_journal 20 --debug_osd 20 --debug_filestore 20 --debug_ebofs 20
key_fn=dev/osd$osd/osd$osd.keys.bin
- $SUDO $CEPH_BIN/authtool --gen-key $key_fn
+ cat <<EOF > $osd_caps
+; generated by vstart.sh on `date`
+ mon = "allow"
+ osd = "allow"
+EOF
+ $SUDO $CEPH_BIN/authtool --gen-key --name=osd.$osd --caps=$osd_caps $key_fn
$SUDO $CEPH_ADM -i $key_fn auth add osd.$osd
fi
echo start osd$osd
[mds.$name]
keys file = $key_fn
EOF
- $SUDO $CEPH_BIN/authtool --gen-key $key_fn
+ cat <<EOF > $osd_caps
+; generated by vstart.sh on `date`
+ mon = "allow"
+ osd = "allow"
+ mds = "allow"
+EOF
+ $SUDO $CEPH_BIN/authtool --gen-key --name=mds.$name --caps=$mds_caps $key_fn
$SUDO $CEPH_ADM -i $key_fn auth add mds.$name
fi