mirror of
https://github.com/ceph/ceph
synced 2024-12-16 00:15:35 +00:00
rgw: limit number of buckets per user
Adding a configurable max_buckets per user. Bucket creation verifies that max_buckets has not reached. Backport: dho Signed-off-by: Yehuda Sadeh <yehuda@inktank.com> Reviewed-by: Sage Weil <sage@inktank.com>
This commit is contained in:
parent
0adb33d867
commit
5db4509b8e
@ -314,6 +314,7 @@ static void show_user_info(RGWUserInfo& info, Formatter *formatter)
|
||||
formatter->dump_string("display_name", info.display_name);
|
||||
formatter->dump_string("email", info.user_email);
|
||||
formatter->dump_int("suspended", (int)info.suspended);
|
||||
formatter->dump_int("max_buckets", (int)info.max_buckets);
|
||||
|
||||
// subusers
|
||||
formatter->open_array_section("subusers");
|
||||
@ -565,6 +566,7 @@ int main(int argc, char **argv)
|
||||
int skip_zero_entries = false; // log show
|
||||
int purge_keys = false;
|
||||
int yes_i_really_mean_it = false;
|
||||
int max_buckets = -1;
|
||||
|
||||
std::string val;
|
||||
std::ostringstream errs;
|
||||
@ -619,6 +621,8 @@ int main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
auid = tmp;
|
||||
} else if (ceph_argparse_witharg(args, i, &val, "--max-buckets", (char*)NULL)) {
|
||||
max_buckets = atoi(val.c_str());
|
||||
} else if (ceph_argparse_witharg(args, i, &val, "--date", (char*)NULL)) {
|
||||
date = val;
|
||||
if (end_date.empty())
|
||||
@ -876,6 +880,8 @@ int main(int argc, char **argv)
|
||||
case OPT_KEY_CREATE:
|
||||
if (!user_id.empty())
|
||||
info.user_id = user_id;
|
||||
if (max_buckets >= 0)
|
||||
info.max_buckets = max_buckets;
|
||||
if (key_type == KEY_TYPE_SWIFT) {
|
||||
access_key = info.user_id;
|
||||
access_key.append(":");
|
||||
|
@ -66,6 +66,8 @@ using ceph::crypto::MD5;
|
||||
|
||||
#define RGW_SUSPENDED_USER_AUID (uint64_t)-2
|
||||
|
||||
#define RGW_DEFAULT_MAX_BUCKETS 1000
|
||||
|
||||
#define CGI_PRINTF(state, format, ...) do { \
|
||||
int __ret = FCGX_FPrintF(state->fcgx->out, format, __VA_ARGS__); \
|
||||
if (state->header_ended) \
|
||||
@ -117,6 +119,7 @@ using ceph::crypto::MD5;
|
||||
#define ERR_INVALID_UTF8 2017
|
||||
#define ERR_UNPROCESSABLE_ENTITY 2018
|
||||
#define ERR_TOO_LARGE 2019
|
||||
#define ERR_TOO_MANY_BUCKETS 2020
|
||||
#define ERR_USER_SUSPENDED 2100
|
||||
#define ERR_INTERNAL_ERROR 2200
|
||||
|
||||
@ -328,11 +331,12 @@ struct RGWUserInfo
|
||||
map<string, RGWAccessKey> swift_keys;
|
||||
map<string, RGWSubUser> subusers;
|
||||
__u8 suspended;
|
||||
uint32_t max_buckets;
|
||||
|
||||
RGWUserInfo() : auid(0), suspended(0) {}
|
||||
RGWUserInfo() : auid(0), suspended(0), max_buckets(RGW_DEFAULT_MAX_BUCKETS) {}
|
||||
|
||||
void encode(bufferlist& bl) const {
|
||||
ENCODE_START(9, 9, bl);
|
||||
ENCODE_START(10, 9, bl);
|
||||
::encode(auid, bl);
|
||||
string access_key;
|
||||
string secret_key;
|
||||
@ -361,10 +365,11 @@ struct RGWUserInfo
|
||||
::encode(subusers, bl);
|
||||
::encode(suspended, bl);
|
||||
::encode(swift_keys, bl);
|
||||
::encode(max_buckets, bl);
|
||||
ENCODE_FINISH(bl);
|
||||
}
|
||||
void decode(bufferlist::iterator& bl) {
|
||||
DECODE_START_LEGACY_COMPAT_LEN_32(9, 9, 9, bl);
|
||||
DECODE_START_LEGACY_COMPAT_LEN_32(10, 9, 9, bl);
|
||||
if (struct_v >= 2) ::decode(auid, bl);
|
||||
else auid = CEPH_AUTH_UID_DEFAULT;
|
||||
string access_key;
|
||||
@ -398,6 +403,11 @@ struct RGWUserInfo
|
||||
if (struct_v >= 8) {
|
||||
::decode(swift_keys, bl);
|
||||
}
|
||||
if (struct_v >= 10) {
|
||||
::decode(max_buckets, bl);
|
||||
} else {
|
||||
max_buckets = RGW_DEFAULT_MAX_BUCKETS;
|
||||
}
|
||||
DECODE_FINISH(bl);
|
||||
}
|
||||
void dump(Formatter *f) const;
|
||||
|
@ -533,6 +533,17 @@ int RGWCreateBucket::verify_permission()
|
||||
if (!rgw_user_is_authenticated(s->user))
|
||||
return -EACCES;
|
||||
|
||||
if (s->user.max_buckets) {
|
||||
RGWUserBuckets buckets;
|
||||
int ret = rgw_read_user_buckets(s->user.user_id, buckets, false);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (buckets.count() >= s->user.max_buckets) {
|
||||
return -ERR_TOO_MANY_BUCKETS;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -49,6 +49,7 @@ const static struct rgw_html_errors RGW_HTML_ERRORS[] = {
|
||||
{ ERR_INVALID_PART_ORDER, 400, "InvalidPartOrder" },
|
||||
{ ERR_REQUEST_TIMEOUT, 400, "RequestTimeout" },
|
||||
{ ERR_TOO_LARGE, 400, "EntityTooLarge" },
|
||||
{ ERR_TOO_MANY_BUCKETS, 400, "TooManyBuckets" },
|
||||
{ ERR_LENGTH_REQUIRED, 411, "MissingContentLength" },
|
||||
{ EACCES, 403, "AccessDenied" },
|
||||
{ EPERM, 403, "AccessDenied" },
|
||||
|
@ -120,6 +120,8 @@ public:
|
||||
* Cleanup data structure
|
||||
*/
|
||||
void clear() { buckets.clear(); }
|
||||
|
||||
size_t count() { return buckets.size(); }
|
||||
};
|
||||
WRITE_CLASS_ENCODER(RGWUserBuckets)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user