From: Zhang Shaowen Date: Fri, 30 Dec 2016 01:38:28 +0000 (+0800) Subject: rgw: add lifecycle validation according to S3. X-Git-Tag: v12.0.0~149^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=7f0cf8e862501c40c476c1fe02cf20f30b8d3e3d;p=ceph.git rgw: add lifecycle validation according to S3. Fixes: http://tracker.ceph.com/issues/18394 Signed-off-by: Zhang Shaowen --- diff --git a/src/rgw/rgw_lc.cc b/src/rgw/rgw_lc.cc index 0aa1a23d3864..4760ea9d393d 100644 --- a/src/rgw/rgw_lc.cc +++ b/src/rgw/rgw_lc.cc @@ -30,6 +30,18 @@ const char* LC_STATUS[] = { using namespace std; using namespace librados; + +bool LCRule::validate() +{ + if (id.length() > MAX_ID_LEN) + return false; + else if (status.compare("Enabled") != 0 && status.compare("Disabled") != 0) + return false; + else if (expiration.get_days() <= 0) + return false; + return true; +} + void RGWLifecycleConfiguration::add_rule(LCRule *rule) { string id; @@ -43,6 +55,49 @@ void RGWLifecycleConfiguration::_add_rule(LCRule *rule) prefix_map[rule->get_prefix()] = rule->get_expiration().get_days(); } +bool RGWLifecycleConfiguration::check_and_add_rule(LCRule *rule) +{ + if (!rule->validate()) + return false; + string id; + rule->get_id(id); + if (rule_map.find(id) != rule_map.end()) //id shouldn't be the same + return false; + rule_map.insert(pair(id, *rule)); + + auto ret = prefix_map.insert(pair(rule->get_prefix(), rule->get_expiration().get_days())); + //Now prefix shouldn't be the same. When we add noncurrent expiration or other action, prefix may be same. + if (!ret.second) + return false; + return true; +} + +//Rules are conflicted: if one rule's prefix starts with other rule's prefix, and these two rules +//define same action(now only support expiration days). +bool RGWLifecycleConfiguration::validate() +{ + if (prefix_map.size() < 2) + return true; + auto next_iter = prefix_map.begin(); + auto cur_iter = next_iter++; + while (next_iter != prefix_map.end()) { + string c_pre = cur_iter->first; + string n_pre = next_iter->first; + if (c_pre.length() > n_pre.length()) { + if (c_pre.compare(0, n_pre.length(), n_pre) == 0) { + return false; + } + } else { + if (n_pre.compare(0, c_pre.length(), c_pre) == 0) { + return false; + } + } + ++next_iter; + ++cur_iter; + } + return true; +} + void *RGWLC::LCWorker::entry() { do { utime_t start = ceph_clock_now(); diff --git a/src/rgw/rgw_lc.h b/src/rgw/rgw_lc.h index d34f63dd3848..c33032f1c113 100644 --- a/src/rgw/rgw_lc.h +++ b/src/rgw/rgw_lc.h @@ -20,6 +20,7 @@ using namespace std; #define HASH_PRIME 7877 +#define MAX_ID_LEN 255 static string lc_oid_prefix = "lc"; static string lc_index_lock_name = "lc_process"; @@ -102,6 +103,8 @@ public: void set_expiration(LCExpiration*_expiration) { expiration = *_expiration; } + + bool validate(); void encode(bufferlist& bl) const { ENCODE_START(1, 1, bl); @@ -162,6 +165,10 @@ public: void add_rule(LCRule* rule); + bool check_and_add_rule(LCRule* rule); + + bool validate(); + multimap& get_rule_map() { return rule_map; } map& get_prefix_map() { return prefix_map; } /* diff --git a/src/rgw/rgw_lc_s3.cc b/src/rgw/rgw_lc_s3.cc index cc05a2a35906..c42b2975c598 100644 --- a/src/rgw/rgw_lc_s3.cc +++ b/src/rgw/rgw_lc_s3.cc @@ -81,13 +81,11 @@ int RGWLifecycleConfiguration_S3::rebuild(RGWRados *store, RGWLifecycleConfigura multimap::iterator iter; for (iter = rule_map.begin(); iter != rule_map.end(); ++iter) { LCRule& src_rule = iter->second; - bool rule_ok = true; - - if (rule_ok) { - dest.add_rule(&src_rule); - } + if (!dest.check_and_add_rule(&src_rule)) + return -EINVAL; } - + if (!dest.validate()) + return -EINVAL; return 0; } diff --git a/src/rgw/rgw_op.cc b/src/rgw/rgw_op.cc index 29a272184ebc..9691dcb3c09f 100644 --- a/src/rgw/rgw_op.cc +++ b/src/rgw/rgw_op.cc @@ -4236,7 +4236,7 @@ void RGWPutLC::execute() ldout(s->cct, 15) << "read len=" << len << " data=" << (data ? data : "") << dendl; if (!parser.parse(data, len, 1)) { - op_ret = -EACCES; + op_ret = -EINVAL; return; } config = static_cast(parser.find_first("LifecycleConfiguration"));