From c167a28d73b665f7239f8fe7cd78851ca46af286 Mon Sep 17 00:00:00 2001 From: Yehuda Sadeh Date: Mon, 23 May 2011 15:12:48 -0700 Subject: [PATCH] rgw: subuser permissions --- src/rgw/rgw_admin.cc | 64 ++++++++++++++++++++++++++++++++++++++++++ src/rgw/rgw_common.cc | 6 ++-- src/rgw/rgw_common.h | 11 ++++---- src/rgw/rgw_op.cc | 5 ++-- src/rgw/rgw_rest_s3.cc | 12 ++++++++ 5 files changed, 88 insertions(+), 10 deletions(-) diff --git a/src/rgw/rgw_admin.cc b/src/rgw/rgw_admin.cc index d722c333f07ea..66237bd41e3a3 100644 --- a/src/rgw/rgw_admin.cc +++ b/src/rgw/rgw_admin.cc @@ -41,6 +41,8 @@ void usage() cerr << " --auth_uid= librados uid\n"; cerr << " --secret= S3 key\n"; cerr << " --os-secret= OpenStack key\n"; + cerr << " --access= Set access permissions for sub-user, should be one\n"; + cerr << " of read, write, readwrite, full\n"; cerr << " --display-name=\n"; cerr << " --bucket=\n"; cerr << " --object=\n"; @@ -61,6 +63,59 @@ enum { OPT_LOG_SHOW, }; +static uint32_t str_to_perm(const char *str) +{ + if (strcasecmp(str, "read") == 0) + return RGW_PERM_READ; + else if (strcasecmp(str, "write") == 0) + return RGW_PERM_WRITE; + else if (strcasecmp(str, "readwrite") == 0) + return RGW_PERM_READ | RGW_PERM_WRITE; + else if (strcasecmp(str, "full") == 0) + return RGW_PERM_FULL_CONTROL; + + usage(); + return 0; // unreachable +} + +struct rgw_flags_desc { + int mask; + const char *str; +}; + +static struct rgw_flags_desc rgw_perms[] = { + { RGW_PERM_FULL_CONTROL, "full-control" }, + { RGW_PERM_READ | RGW_PERM_WRITE, "read-write" }, + { RGW_PERM_READ, "read" }, + { RGW_PERM_WRITE, "write" }, + { RGW_PERM_READ_ACP, "read-acp" }, + { RGW_PERM_WRITE_ACP, "read-acp" }, + { 0, NULL } +}; + +static void perm_to_str(uint32_t mask, char *buf, int len) +{ + const char *sep = ""; + int pos = 0; + while (mask) { + int orig_mask = mask; + for (int i = 0; rgw_perms[i].mask; i++) { + struct rgw_flags_desc *desc = &rgw_perms[i]; + if ((mask & desc->mask) == desc->mask) { + pos += snprintf(buf + pos, len - pos, "%s%s", sep, desc->str); + if (pos == len) + return; + sep = ", "; + mask &= ~desc->mask; + if (!mask) + return; + } + } + if (mask == orig_mask) // no change + break; + } +} + static int get_cmd(const char *cmd, const char *prev_cmd, bool *need_more) { *need_more = false; @@ -189,6 +244,8 @@ int main(int argc, char **argv) const char *openstack_key = 0; const char *date = 0; char *subuser = 0; + const char *access = 0; + uint32_t perm_mask = 0; uint64_t auid = 0; RGWUserInfo info; RGWAccess *store; @@ -229,6 +286,9 @@ int main(int argc, char **argv) CEPH_ARGPARSE_SET_ARG_VAL(&openstack_key, OPT_STR); } else if (CEPH_ARGPARSE_EQ("date", '\0')) { CEPH_ARGPARSE_SET_ARG_VAL(&date, OPT_STR); + } else if (CEPH_ARGPARSE_EQ("access", '\0')) { + CEPH_ARGPARSE_SET_ARG_VAL(&access, OPT_STR); + perm_mask = str_to_perm(access); } else { if (!opt_cmd) { opt_cmd = get_cmd(CEPH_ARGPARSE_VAL, prev_cmd, &need_more); @@ -366,6 +426,7 @@ int main(int argc, char **argv) if (subuser) { RGWSubUser u; u.name = subuser; + u.perm_mask = perm_mask; info.subusers[subuser] = u; } @@ -389,6 +450,9 @@ int main(int argc, char **argv) for (uiter = info.subusers.begin(); uiter != info.subusers.end(); ++uiter) { RGWSubUser& u = uiter->second; cout << " Name: " << info.user_id << ":" << u.name << std::endl; + char buf[256]; + perm_to_str(u.perm_mask, buf, sizeof(buf)); + cout << " Permissions: " << buf << std::endl; } cout << "Display Name: " << info.display_name << std::endl; cout << "Email: " << info.user_email << std::endl; diff --git a/src/rgw/rgw_common.cc b/src/rgw/rgw_common.cc index 2b09c72c503cb..ebe9bd637196f 100644 --- a/src/rgw/rgw_common.cc +++ b/src/rgw/rgw_common.cc @@ -138,19 +138,19 @@ string& XMLArgs::get(const char *name) return get(s); } -bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int perm) +bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int user_perm_mask, int perm) { if (!policy) return false; - int acl_perm = policy->get_perm(uid, perm); + int acl_perm = policy->get_perm(uid, perm) & user_perm_mask; return (perm == acl_perm); } bool verify_permission(struct req_state *s, int perm) { - return verify_permission(s->acl, s->user.user_id, perm); + return verify_permission(s->acl, s->user.user_id, s->perm_mask, perm); } static char hex_to_num(char c) diff --git a/src/rgw/rgw_common.h b/src/rgw/rgw_common.h index b4c4774d8aac2..d8b049b30df55 100644 --- a/src/rgw/rgw_common.h +++ b/src/rgw/rgw_common.h @@ -181,21 +181,21 @@ WRITE_CLASS_ENCODER(RGWAccessKey); struct RGWSubUser { string name; - uint32_t flags; + uint32_t perm_mask; - RGWSubUser() {} + RGWSubUser() : perm_mask(0) {} void encode(bufferlist& bl) const { __u32 ver = 1; ::encode(ver, bl); ::encode(name, bl); - ::encode(flags, bl); + ::encode(perm_mask, bl); } void decode(bufferlist::iterator& bl) { __u32 ver; ::decode(ver, bl); ::decode(name, bl); - ::decode(flags, bl); + ::decode(perm_mask, bl); } }; WRITE_CLASS_ENCODER(RGWSubUser); @@ -328,6 +328,7 @@ struct req_state { uint64_t bytes_received; // data received uint64_t obj_size; bool should_log; + uint32_t perm_mask; XMLArgs args; @@ -434,7 +435,7 @@ static inline int rgw_str_to_bool(const char *s, int def_val) /** */ extern int parse_time(const char *time_str, time_t *time); /** Check if a user has a permission on that ACL */ -extern bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int perm); +extern bool verify_permission(RGWAccessControlPolicy *policy, string& uid, int user_perm_mask, int perm); /** Check if the req_state's user has the necessary permissions * to do the requested action */ extern bool verify_permission(struct req_state *s, int perm); diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 315273be9d36c..bf07e7553457c 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -118,7 +118,7 @@ int read_acls(struct req_state *s, RGWAccessControlPolicy *policy, string& bucke if (ret < 0) return ret; - if (!verify_permission(&bucket_policy, s->user.user_id, RGW_PERM_READ)) + if (!verify_permission(&bucket_policy, s->user.user_id, s->perm_mask, RGW_PERM_READ)) ret = -EACCES; else ret = -ENOENT; @@ -530,7 +530,7 @@ int RGWCopyObj::init_common() if (ret < 0) return ret; - if (!verify_permission(&src_policy, s->user.user_id, RGW_PERM_READ)) { + if (!verify_permission(&src_policy, s->user.user_id, s->perm_mask, RGW_PERM_READ)) { ret = -EACCES; return ret; } @@ -813,6 +813,7 @@ void RGWHandler::init_state(struct req_state *s, struct fcgx_state *fcgx) s->os_groups = NULL; s->time = g_clock.now(); s->user.clear(); + s->perm_mask = 0; } int RGWHandler::do_read_permissions(bool only_bucket) diff --git a/src/rgw/rgw_rest_s3.cc b/src/rgw/rgw_rest_s3.cc index fec2e4702af5f..3d5f6e26bd3aa 100644 --- a/src/rgw/rgw_rest_s3.cc +++ b/src/rgw/rgw_rest_s3.cc @@ -5,6 +5,7 @@ #include "rgw_rest.h" #include "rgw_rest_s3.h" +#include "rgw_acl.h" #include "common/armor.h" @@ -436,6 +437,17 @@ bool RGWHandler_REST_S3::authorize(struct req_state *s) const char *key = k.key.c_str(); int key_len = k.key.size(); + if (!k.subuser.empty()) { + map::iterator uiter = s->user.subusers.find(k.subuser); + if (uiter == s->user.subusers.end()) { + RGW_LOG(0) << "ERROR: could not find subuser: " << k.subuser << dendl; + return false; + } + RGWSubUser& subuser = uiter->second; + s->perm_mask = subuser.perm_mask; + } else + s->perm_mask = RGW_PERM_FULL_CONTROL; + char hmac_sha1[CEPH_CRYPTO_HMACSHA1_DIGESTSIZE]; calc_hmac_sha1(key, key_len, auth_hdr.c_str(), auth_hdr.size(), hmac_sha1); -- 2.39.5