rgw: multiple swift keys per user

This commit is contained in:
Yehuda Sadeh 2011-10-11 10:49:27 -07:00
parent 9b18e55e86
commit f883e6382f
5 changed files with 110 additions and 54 deletions

View File

@ -56,15 +56,14 @@ void _usage()
cerr << " specified date (and optional time)\n";
cerr << "options:\n";
cerr << " --uid=<id> user id\n";
cerr << " --auth-uid=<auid> librados uid\n";
cerr << " --subuser=<name> subuser name\n";
cerr << " --access-key=<key> S3 access key\n";
cerr << " --swift-user=<group:name> Swift user\n";
cerr << " --email=<email>\n";
cerr << " --auth_uid=<auid> librados uid\n";
cerr << " --secret=<key> S3 key\n";
cerr << " --swift-secret=<key> Swift key\n";
cerr << " --gen-access-key generate random access key\n";
cerr << " --secret=<key> specify secret key\n";
cerr << " --gen-access-key generate random access key (for S3)\n";
cerr << " --gen-secret generate random secret key\n";
cerr << " --key-type=<type> key type, options are: swift, s3\n";
cerr << " --access=<access> Set access permissions for sub-user, should be one\n";
cerr << " of read, write, readwrite, full\n";
cerr << " --display-name=<name>\n";
@ -291,8 +290,6 @@ static void show_user_info(RGWUserInfo& info, Formatter *formatter)
formatter->dump_int("rados_uid", info.auid);
formatter->dump_string("display_name", info.display_name.c_str());
formatter->dump_string("email", info.user_email.c_str());
formatter->dump_string("swift_user", info.swift_name.c_str());
formatter->dump_string("swift_key", info.swift_key.c_str());
formatter->dump_int("suspended", (int)info.suspended);
// keys
@ -323,6 +320,18 @@ static void show_user_info(RGWUserInfo& info, Formatter *formatter)
}
formatter->close_section();
formatter->open_array_section("swift_keys");
for (kiter = info.swift_keys.begin(); kiter != info.swift_keys.end(); ++kiter) {
RGWAccessKey& k = kiter->second;
const char *sep = (k.subuser.empty() ? "" : ":");
const char *subuser = (k.subuser.empty() ? "" : k.subuser.c_str());
formatter->open_object_section("key");
formatter->dump_format("user", "%s%s%s", info.user_id.c_str(), sep, subuser);
formatter->dump_string("secret_key", k.key);
formatter->close_section();
}
formatter->close_section();
formatter->close_section();
formatter->flush(cout);
}
@ -391,12 +400,16 @@ static void remove_old_indexes(RGWUserInfo& old_info, RGWUserInfo new_info)
}
}
if (!old_info.swift_name.empty() &&
old_info.swift_name.compare(new_info.swift_name) != 0) {
ret = rgw_remove_swift_name_index(new_info.user_id, old_info.swift_name);
if (ret < 0 && ret != -ENOENT) {
cerr << "ERROR: could not remove index for swift_name " << old_info.swift_name << " return code: " << ret << std::endl;
success = false;
map<string, RGWAccessKey>::iterator old_iter;
for (old_iter = old_info.swift_keys.begin(); old_iter != old_info.swift_keys.end(); ++old_iter) {
RGWAccessKey& swift_key = old_iter->second;
map<string, RGWAccessKey>::iterator new_iter = new_info.swift_keys.find(swift_key.id);
if (new_iter == new_info.swift_keys.end()) {
ret = rgw_remove_swift_name_index(new_info.user_id, swift_key.id);
if (ret < 0 && ret != -ENOENT) {
cerr << "ERROR: could not remove index for swift_name " << swift_key.id << " return code: " << ret << std::endl;
success = false;
}
}
}
@ -443,6 +456,11 @@ int bucket_stats(rgw_bucket& bucket, Formatter *formatter)
return 0;
}
enum KeyType {
KEY_TYPE_SWIFT,
KEY_TYPE_S3,
};
int main(int argc, char **argv)
{
vector<const char*> args;
@ -453,8 +471,10 @@ int main(int argc, char **argv)
common_init_finish(g_ceph_context);
std::string user_id, access_key, secret_key, user_email, display_name;
std::string bucket_name, pool_name, object, swift_user, swift_key;
std::string bucket_name, pool_name, object;
std::string date, time, subuser, access, format;
std::string key_type_str;
KeyType key_type = KEY_TYPE_S3;
rgw_bucket bucket;
uint32_t perm_mask = 0;
uint64_t auid = -1;
@ -500,6 +520,16 @@ int main(int argc, char **argv)
pool_name = val;
} else if (ceph_argparse_witharg(args, i, &val, "-o", "--object", (char*)NULL)) {
object = val;
} else if (ceph_argparse_witharg(args, i, &val, "--key-type", (char*)NULL)) {
key_type_str = val;
if (key_type_str.compare("swift") == 0) {
key_type = KEY_TYPE_SWIFT;
} else if (key_type_str.compare("s3") == 0) {
key_type = KEY_TYPE_S3;
} else {
cerr << "bad key type: " << key_type_str << std::endl;
return usage();
}
} else if (ceph_argparse_flag(args, i, "--gen-access-key", (char*)NULL)) {
gen_key = true;
} else if (ceph_argparse_flag(args, i, "--gen-secret", (char*)NULL)) {
@ -510,10 +540,6 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE);
}
auid = tmp;
} else if (ceph_argparse_witharg(args, i, &val, "--swift-user", (char*)NULL)) {
swift_user = val;
} else if (ceph_argparse_witharg(args, i, &val, "--swift-secret", (char*)NULL)) {
swift_key = val;
} else if (ceph_argparse_witharg(args, i, &val, "--date", (char*)NULL)) {
date = val;
} else if (ceph_argparse_witharg(args, i, &val, "--time", (char*)NULL)) {
@ -631,13 +657,6 @@ int main(int argc, char **argv)
cerr << "could not find user by specified access key" << std::endl;
}
}
if (!found && (!swift_user.empty())) {
s = swift_user;
if (rgw_get_user_info_by_swift(s, info) >= 0) {
found = true;
} else
cerr << "could not find user by specified swift username" << std::endl;
}
if (found)
user_id = info.user_id.c_str();
}
@ -760,15 +779,23 @@ int main(int argc, char **argv)
case OPT_KEY_CREATE:
if (!user_id.empty())
info.user_id = user_id;
if (key_type == KEY_TYPE_SWIFT)
access_key = subuser;
if ((!access_key.empty()) && (!secret_key.empty())) {
RGWAccessKey k;
k.id = access_key;
k.key = secret_key;
if (!subuser.empty())
k.subuser = subuser;
info.access_keys[access_key] = k;
if (key_type == KEY_TYPE_SWIFT)
info.swift_keys[access_key] = k;
else
info.access_keys[access_key] = k;
} else if ((!access_key.empty()) || (!secret_key.empty())) {
cerr << "access key modification requires both access key and secret key" << std::endl;
if (key_type == KEY_TYPE_SWIFT)
cerr << "swift key modification requires both subuser and secret key" << std::endl;
else
cerr << "access key modification requires both access key and secret key" << std::endl;
return 1;
}
if (!display_name.empty())
@ -777,10 +804,6 @@ int main(int argc, char **argv)
info.user_email = user_email;
if (auid != (uint64_t)-1)
info.auid = auid;
if (!swift_user.empty())
info.swift_name = swift_user;
if (!swift_key.empty())
info.swift_key = swift_key;
if (!subuser.empty()) {
RGWSubUser u;
u.name = subuser;

View File

@ -57,7 +57,7 @@ using ceph::crypto::MD5;
#define RGW_BUCKETS_OBJ_PREFIX ".buckets"
#define USER_INFO_VER 7
#define USER_INFO_VER 8
#define RGW_MAX_CHUNK_SIZE (512*1024)
#define RGW_MAX_PENDING_CHUNKS 16
@ -279,9 +279,8 @@ struct RGWUserInfo
string user_id;
string display_name;
string user_email;
string swift_name;
string swift_key;
map<string, RGWAccessKey> access_keys;
map<string, RGWAccessKey> swift_keys;
map<string, RGWSubUser> subusers;
__u8 suspended;
@ -303,12 +302,21 @@ struct RGWUserInfo
::encode(secret_key, bl);
::encode(display_name, bl);
::encode(user_email, bl);
string swift_name;
string swift_key;
if (!swift_keys.empty()) {
map<string, RGWAccessKey>::const_iterator iter = swift_keys.begin();
const RGWAccessKey& k = iter->second;
swift_name = k.id;
swift_key = k.key;
}
::encode(swift_name, bl);
::encode(swift_key, bl);
::encode(user_id, bl);
::encode(access_keys, bl);
::encode(subusers, bl);
::encode(suspended, bl);
::encode(swift_keys, bl);
}
void decode(bufferlist::iterator& bl) {
__u32 ver;
@ -327,6 +335,8 @@ struct RGWUserInfo
}
::decode(display_name, bl);
::decode(user_email, bl);
string swift_name;
string swift_key;
if (ver >= 3) ::decode(swift_name, bl);
if (ver >= 4) ::decode(swift_key, bl);
if (ver >= 5)
@ -341,6 +351,9 @@ struct RGWUserInfo
if (ver >= 7) {
::decode(suspended, bl);
}
if (ver >= 8) {
::decode(swift_keys, bl);
}
}
void clear() {

View File

@ -12,9 +12,9 @@ using namespace ceph::crypto;
static RGW_SWIFT_Auth_Get rgw_swift_auth_get;
static int build_token(string& os_user, string& key, uint64_t nonce, utime_t& expiration, bufferlist& bl)
static int build_token(string& swift_user, string& key, uint64_t nonce, utime_t& expiration, bufferlist& bl)
{
::encode(os_user, bl);
::encode(swift_user, bl);
::encode(nonce, bl);
::encode(expiration, bl);
@ -38,7 +38,7 @@ static int build_token(string& os_user, string& key, uint64_t nonce, utime_t& ex
}
static int encode_token(string& os_user, string& key, bufferlist& bl)
static int encode_token(string& swift_user, string& key, bufferlist& bl)
{
uint64_t nonce;
@ -49,7 +49,7 @@ static int encode_token(string& os_user, string& key, bufferlist& bl)
utime_t expiration = ceph_clock_now(g_ceph_context);
expiration += RGW_SWIFT_TOKEN_EXPIRATION; // 15 minutes
ret = build_token(os_user, key, nonce, expiration, bl);
ret = build_token(swift_user, key, nonce, expiration, bl);
return ret;
}
@ -79,10 +79,10 @@ int rgw_swift_verify_signed_token(const char *token, RGWUserInfo& info)
uint64_t nonce;
utime_t expiration;
string os_user;
string swift_user;
try {
::decode(os_user, iter);
::decode(swift_user, iter);
::decode(nonce, iter);
::decode(expiration, iter);
} catch (buffer::error& err) {
@ -94,13 +94,18 @@ int rgw_swift_verify_signed_token(const char *token, RGWUserInfo& info)
return -EPERM;
}
if ((ret = rgw_get_user_info_by_swift(os_user, info)) < 0)
if ((ret = rgw_get_user_info_by_swift(swift_user, info)) < 0)
return ret;
dout(10) << "os_user=" << os_user << dendl;
dout(10) << "swift_user=" << swift_user << dendl;
map<string, RGWAccessKey>::iterator siter = info.swift_keys.find(swift_user);
if (siter == info.swift_keys.end())
return -EPERM;
RGWAccessKey& swift_key = siter->second;
bufferlist tok;
ret = build_token(os_user, info.swift_key, nonce, expiration, tok);
ret = build_token(swift_user, swift_key.key, nonce, expiration, tok);
if (ret < 0)
return ret;
@ -131,6 +136,8 @@ void RGW_SWIFT_Auth_Get::execute()
string user_str = user;
RGWUserInfo info;
bufferlist bl;
RGWAccessKey *swift_key;
map<string, RGWAccessKey>::iterator siter;
if (g_conf->rgw_swift_url.length() == 0 ||
g_conf->rgw_swift_url_prefix.length() == 0) {
@ -145,7 +152,14 @@ void RGW_SWIFT_Auth_Get::execute()
if ((ret = rgw_get_user_info_by_swift(user_str, info)) < 0)
goto done;
if (info.swift_key.compare(key) != 0) {
siter = info.swift_keys.find(user_str);
if (siter == info.swift_keys.end()) {
ret = -EPERM;
goto done;
}
swift_key = &siter->second;
if (swift_key->key.compare(key) != 0) {
dout(0) << "RGW_SWIFT_Auth_Get::execute(): bad swift key" << dendl;
ret = -EPERM;
goto done;
@ -154,7 +168,7 @@ void RGW_SWIFT_Auth_Get::execute()
CGI_PRINTF(s, "X-Storage-Url: %s/%s/v1/AUTH_rgw\n", g_conf->rgw_swift_url.c_str(),
g_conf->rgw_swift_url_prefix.c_str());
if ((ret = encode_token(info.swift_name, info.swift_key, bl)) < 0)
if ((ret = encode_token(swift_key->id, swift_key->key, bl)) < 0)
goto done;
{

View File

@ -48,10 +48,12 @@ int rgw_store_user_info(RGWUserInfo& info)
int ret;
map<string,bufferlist> attrs;
if (info.swift_name.size()) {
map<string, RGWAccessKey>::iterator iter;
for (iter = info.swift_keys.begin(); iter != info.swift_keys.end(); ++iter) {
RGWAccessKey& k = iter->second;
/* check if swift mapping exists */
RGWUserInfo inf;
int r = rgw_get_user_info_by_swift(info.swift_name, inf);
int r = rgw_get_user_info_by_swift(k.id, inf);
if (r >= 0 && inf.user_id.compare(info.user_id) != 0) {
dout(0) << "can't store user info, swift id already mapped to another user" << dendl;
return -EEXIST;
@ -98,8 +100,13 @@ int rgw_store_user_info(RGWUserInfo& info)
}
}
if (info.swift_name.size())
ret = rgw_put_obj(info.user_id, ui_swift_bucket, info.swift_name, uid_bl.c_str(), uid_bl.length());
map<string, RGWAccessKey>::iterator siter;
for (siter = info.swift_keys.begin(); siter != info.swift_keys.end(); ++siter) {
RGWAccessKey& k = siter->second;
ret = rgw_put_obj(info.user_id, ui_swift_bucket, k.id, uid_bl.c_str(), uid_bl.length());
if (ret < 0)
return ret;
}
return ret;
}

View File

@ -28,15 +28,14 @@
specified date (and optional time)
options:
--uid=<id> user id
--auth-uid=<auid> librados uid
--subuser=<name> subuser name
--access-key=<key> S3 access key
--swift-user=<group:name> Swift user
--email=<email>
--auth_uid=<auid> librados uid
--secret=<key> S3 key
--swift-secret=<key> Swift key
--gen-access-key generate random access key
--secret=<key> specify secret key
--gen-access-key generate random access key (for S3)
--gen-secret generate random secret key
--key-type=<type> key type, options are: swift, s3
--access=<access> Set access permissions for sub-user, should be one
of read, write, readwrite, full
--display-name=<name>