rgw_sts.cc
rgw_rest_sts.cc
rgw_perf_counters.cc
- rgw_rest_iam.cc)
+ rgw_rest_iam.cc
+ rgw_object_lock.cc)
if(WITH_RADOSGW_AMQP_ENDPOINT)
list(APPEND librgw_common_srcs rgw_amqp.cc)
"versionId",
"versioning",
"versions",
- "website"
+ "website",
+ "object-lock"
};
/*
{ ERR_NO_SUCH_SUBUSER, {404, "NoSuchSubUser"}},
{ ERR_NO_SUCH_ENTITY, {404, "NoSuchEntity"}},
{ ERR_NO_SUCH_CORS_CONFIGURATION, {404, "NoSuchCORSConfiguration"}},
+ { ERR_NO_SUCH_OBJECT_LOCK_CONFIGURATION, {404, "NoSuchObjectLockConfiguration"}},
{ ERR_METHOD_NOT_ALLOWED, {405, "MethodNotAllowed" }},
{ ETIMEDOUT, {408, "RequestTimeout" }},
{ EEXIST, {409, "BucketAlreadyExists" }},
#include "rgw_string.h"
#include "common/async/yield_context.h"
#include "rgw_website.h"
+#include "rgw_object_lock.h"
#include "cls/version/cls_version_types.h"
#include "cls/user/cls_user_types.h"
#include "cls/rgw/cls_rgw_types.h"
#define RGW_ATTR_X_ROBOTS_TAG RGW_ATTR_PREFIX "x-robots-tag"
#define RGW_ATTR_STORAGE_CLASS RGW_ATTR_PREFIX "storage_class"
+/* S3 Object Lock*/
+#define RGW_ATTR_OBJECT_LOCK RGW_ATTR_PREFIX "object-lock"
+#define RGW_ATTR_OBJECT_RETENTION RGW_ATTR_PREFIX "object-retention"
+#define RGW_ATTR_OBJECT_LEGAL_HOLD RGW_ATTR_PREFIX "object-legal-hold"
+#define RGW_ATTR_OBJECT_LOCK_MODE RGW_ATTR_PREFIX "object-lock-mode"
+#define RGW_ATTR_OBJECT_LOCK_UNTIL_DATE RGW_ATTR_PREFIX "object-lock-until-date"
+
+
#define RGW_ATTR_PG_VER RGW_ATTR_PREFIX "pg_ver"
#define RGW_ATTR_SOURCE_ZONE RGW_ATTR_PREFIX "source_zone"
#define RGW_ATTR_TAGS RGW_ATTR_PREFIX RGW_AMZ_PREFIX "tagging"
#define ERR_NO_SUCH_SUBUSER 2043
#define ERR_MFA_REQUIRED 2044
#define ERR_NO_SUCH_CORS_CONFIGURATION 2045
+#define ERR_NO_SUCH_OBJECT_LOCK_CONFIGURATION 2046
+#define ERR_INVALID_BUCKET_STATE 2047
#define ERR_USER_SUSPENDED 2100
#define ERR_INTERNAL_ERROR 2200
#define ERR_NOT_IMPLEMENTED 2201
RGW_OP_GET_USER_POLICY,
RGW_OP_LIST_USER_POLICIES,
RGW_OP_DELETE_USER_POLICY,
+ RGW_OP_PUT_BUCKET_OBJ_LOCK,
+ RGW_OP_GET_BUCKET_OBJ_LOCK,
+ RGW_OP_PUT_OBJ_RETENTION,
+ RGW_OP_GET_OBJ_RETENTION,
+ RGW_OP_PUT_OBJ_LEGAL_HOLD,
+ RGW_OP_GET_OBJ_LEGAL_HOLD,
/* rgw specific */
RGW_OP_ADMIN_SET_METADATA,
RGW_OP_GET_OBJ_LAYOUT,
BUCKET_VERSIONS_SUSPENDED = 0x4,
BUCKET_DATASYNC_DISABLED = 0X8,
BUCKET_MFA_ENABLED = 0X10,
+ BUCKET_OBJ_LOCK_ENABLED = 0X20,
};
enum RGWBucketIndexType {
map<string, uint32_t> mdsearch_config;
+
+
/* resharding */
uint8_t reshard_status;
string new_bucket_instance_id;
+ RGWObjectLock obj_lock;
+
void encode(bufferlist& bl) const {
- ENCODE_START(19, 4, bl);
+ ENCODE_START(20, 4, bl);
encode(bucket, bl);
encode(owner.id, bl);
encode(flags, bl);
encode(mdsearch_config, bl);
encode(reshard_status, bl);
encode(new_bucket_instance_id, bl);
+ if (obj_lock_enabled()) {
+ encode(obj_lock, bl);
+ }
ENCODE_FINISH(bl);
}
void decode(bufferlist::const_iterator& bl) {
- DECODE_START_LEGACY_COMPAT_LEN_32(19, 4, 4, bl);
+ DECODE_START_LEGACY_COMPAT_LEN_32(20, 4, 4, bl);
decode(bucket, bl);
if (struct_v >= 2) {
string s;
decode(reshard_status, bl);
decode(new_bucket_instance_id, bl);
}
+ if (struct_v >= 20 && obj_lock_enabled()) {
+ decode(obj_lock, bl);
+ }
DECODE_FINISH(bl);
}
void dump(Formatter *f) const;
bool versioning_enabled() const { return (versioning_status() & (BUCKET_VERSIONED | BUCKET_VERSIONS_SUSPENDED)) == BUCKET_VERSIONED; }
bool mfa_enabled() const { return (versioning_status() & BUCKET_MFA_ENABLED) != 0; }
bool datasync_flag_enabled() const { return (flags & BUCKET_DATASYNC_DISABLED) == 0; }
+ bool obj_lock_enabled() const { return (flags & BUCKET_OBJ_LOCK_ENABLED) != 0; }
bool has_swift_versioning() const {
/* A bucket may be versioned through one mechanism only. */
{ "s3:GetObjectTagging", s3GetObjectTagging },
{ "s3:GetObjectVersionTagging", s3GetObjectVersionTagging},
{ "s3:GetReplicationConfiguration", s3GetReplicationConfiguration },
+ { "s3:GetBucketObjectLockConfiguration", s3GetBucketObjectLockConfiguration},
{ "s3:ListAllMyBuckets", s3ListAllMyBuckets },
{ "s3:ListBucketMultipartUploads", s3ListBucketMultipartUploads },
{ "s3:ListBucket", s3ListBucket },
{ "s3:PutObjectTagging", s3PutObjectTagging },
{ "s3:PutObjectVersionTagging", s3PutObjectVersionTagging },
{ "s3:PutReplicationConfiguration", s3PutReplicationConfiguration },
+ { "s3:PutBucketObjectLockConfiguration", s3PutBucketObjectLockConfiguration},
{ "s3:RestoreObject", s3RestoreObject },
{ "iam:PutUserPolicy", iamPutUserPolicy },
{ "iam:GetUserPolicy", iamGetUserPolicy },
case s3DeleteObjectVersionTagging:
return "s3:DeleteObjectVersionTagging";
+ case s3PutBucketObjectLockConfiguration:
+ return "s3:PutBucketObjectLockConfiguration";
+
+ case s3GetBucketObjectLockConfiguration:
+ return "s3:GetBucketObjectLockConfiguration";
+
case iamPutUserPolicy:
return "iam:PutUserPolicy";
static constexpr std::uint64_t s3GetObjectVersionTagging = 51;
static constexpr std::uint64_t s3PutObjectVersionTagging = 52;
static constexpr std::uint64_t s3DeleteObjectVersionTagging = 53;
-static constexpr std::uint64_t s3All = 54;
-
-static constexpr std::uint64_t iamPutUserPolicy = 55;
-static constexpr std::uint64_t iamGetUserPolicy = 56;
-static constexpr std::uint64_t iamDeleteUserPolicy = 57;
-static constexpr std::uint64_t iamListUserPolicies = 58;
-static constexpr std::uint64_t iamCreateRole = 59;
-static constexpr std::uint64_t iamDeleteRole = 60;
-static constexpr std::uint64_t iamModifyRole = 61;
-static constexpr std::uint64_t iamGetRole = 62;
-static constexpr std::uint64_t iamListRoles = 63;
-static constexpr std::uint64_t iamPutRolePolicy = 64;
-static constexpr std::uint64_t iamGetRolePolicy = 65;
-static constexpr std::uint64_t iamListRolePolicies = 66;
-static constexpr std::uint64_t iamDeleteRolePolicy = 67;
-static constexpr std::uint64_t iamAll = 68;
-static constexpr std::uint64_t stsAssumeRole = 69;
-static constexpr std::uint64_t stsAssumeRoleWithWebIdentity = 70;
-static constexpr std::uint64_t stsGetSessionToken = 71;
-static constexpr std::uint64_t stsAll = 72;
-
-static constexpr std::uint64_t s3Count = s3DeleteObjectVersionTagging + 1;
+static constexpr std::uint64_t s3PutBucketObjectLockConfiguration = 54;
+static constexpr std::uint64_t s3GetBucketObjectLockConfiguration = 55;
+static constexpr std::uint64_t s3PutObjectRetention = 56;
+static constexpr std::uint64_t s3GetObjectRetention = 57;
+static constexpr std::uint64_t s3PutObjectLegalHold = 58;
+static constexpr std::uint64_t s3GetObjectLegalHold = 59;
+static constexpr std::uint64_t s3BypassGovernanceRetention = 60;
+static constexpr std::uint64_t s3All = 61;
+
+static constexpr std::uint64_t iamPutUserPolicy = 62;
+static constexpr std::uint64_t iamGetUserPolicy = 63;
+static constexpr std::uint64_t iamDeleteUserPolicy = 64;
+static constexpr std::uint64_t iamListUserPolicies = 65;
+static constexpr std::uint64_t iamCreateRole = 66;
+static constexpr std::uint64_t iamDeleteRole = 67;
+static constexpr std::uint64_t iamModifyRole = 68;
+static constexpr std::uint64_t iamGetRole = 69;
+static constexpr std::uint64_t iamListRoles = 70;
+static constexpr std::uint64_t iamPutRolePolicy = 71;
+static constexpr std::uint64_t iamGetRolePolicy = 72;
+static constexpr std::uint64_t iamListRolePolicies = 73;
+static constexpr std::uint64_t iamDeleteRolePolicy = 74;
+static constexpr std::uint64_t iamAll = 75;
+static constexpr std::uint64_t stsAssumeRole = 76;
+static constexpr std::uint64_t stsAssumeRoleWithWebIdentity = 77;
+static constexpr std::uint64_t stsGetSessionToken = 78;
+static constexpr std::uint64_t stsAll = 79;
+
+static constexpr std::uint64_t s3Count = s3BypassGovernanceRetention + 1;
static constexpr std::uint64_t allCount = stsAll + 1;
using Action_t = bitset<allCount>;
using NotAction_t = Action_t;
static const Action_t None(0);
-static const Action_t s3AllValue("111111111111111111111111111111111111111111111111111111");
-static const Action_t iamAllValue("11111111111110000000000000000000000000000000000000000000000000000000");
-static const Action_t stsAllValue("111000000000000000000000000000000000000000000000000000000000000000000000");
+static const Action_t s3AllValue("1111111111111111111111111111111111111111111111111111111111111");
+static const Action_t iamAllValue("111111111111100000000000000000000000000000000000000000000000000000000000000");
+static const Action_t stsAllValue("1110000000000000000000000000000000000000000000000000000000000000000000000000000");
//Modify allValue if more Actions are added
-static const Action_t allValue("1111111111111111111111111111111111111111111111111111111111111111111111111");
+static const Action_t allValue("11111111111111111111111111111111111111111111111111111111111111111111111111111111");
namespace {
// Please update the table in doc/radosgw/s3/authentication.rst if you
case s3GetObjectVersionTorrent:
case s3GetObjectTagging:
case s3GetObjectVersionTagging:
+ case s3GetObjectRetention:
+ case s3GetObjectLegalHold:
case s3ListAllMyBuckets:
case s3ListBucket:
case s3ListBucketMultipartUploads:
case s3DeleteObjectTagging:
case s3DeleteObjectVersionTagging:
case s3RestoreObject:
+ case s3PutObjectRetention:
+ case s3PutObjectLegalHold:
return RGW_PERM_WRITE;
case s3GetAccelerateConfiguration:
case s3GetObjectAcl:
case s3GetObjectVersionAcl:
case s3GetReplicationConfiguration:
+ case s3GetBucketObjectLockConfiguration:
return RGW_PERM_READ_ACP;
case s3DeleteBucketPolicy:
case s3PutObjectAcl:
case s3PutObjectVersionAcl:
case s3PutReplicationConfiguration:
+ case s3PutBucketObjectLockConfiguration:
return RGW_PERM_WRITE_ACP;
case s3All:
--- /dev/null
+#include "rgw_object_lock.h"
+
+void DefaultRetention::decode_xml(XMLObj *obj) {
+ RGWXMLDecoder::decode_xml("Mode", mode, obj, true);
+ if (mode.compare("GOVERNANCE") != 0 && mode.compare("COMPLIANCE") != 0) {
+ throw RGWXMLDecoder::err("bad Mode in lock rule");
+ }
+ bool days_exist = RGWXMLDecoder::decode_xml("Days", days, obj);
+ bool years_exist = RGWXMLDecoder::decode_xml("Years", years, obj);
+ if ((days_exist && years_exist) || (!days_exist && !years_exist)) {
+ throw RGWXMLDecoder::err("either Days or Years must be specified, but not both");
+ }
+}
+
+void DefaultRetention::dump_xml(Formatter *f) const {
+ encode_xml("Mode", mode, f);
+ if (days > 0) {
+ encode_xml("Days", days, f);
+ } else {
+ encode_xml("Years", years, f);
+ }
+}
+
+void ObjectLockRule::decode_xml(XMLObj *obj) {
+ RGWXMLDecoder::decode_xml("DefaultRetention", defaultRetention, obj, true);
+}
+
+void ObjectLockRule::dump_xml(Formatter *f) const {
+ encode_xml("DefaultRetention", defaultRetention, f);
+}
+
+void RGWObjectLock::decode_xml(XMLObj *obj) {
+ string enabled_str;
+ RGWXMLDecoder::decode_xml("ObjectLockEnabled", enabled_str, obj, true);
+ if (enabled_str.compare("Enabled") != 0) {
+ throw RGWXMLDecoder::err("invalid ObjectLockEnabled value");
+ } else {
+ enabled = true;
+ }
+ rule_exist = RGWXMLDecoder::decode_xml("Rule", rule, obj);
+}
+
+void RGWObjectLock::dump_xml(Formatter *f) const {
+ if (enabled) {
+ encode_xml("ObjectLockEnabled", "Enabled", f);
+ }
+ if (rule_exist) {
+ encode_xml("Rule", rule, f);
+ }
+}
+
+ceph::real_time RGWObjectLock::get_lock_until_date(const ceph::real_time& mtime) const {
+ if (!rule_exist) {
+ return ceph::real_time();
+ }
+ int days = get_days();
+ if (days <= 0) {
+ days = get_years()*365;
+ }
+ return mtime + make_timespan(days*24*60*60);
+}
+
+void RGWObjectRetention::decode_xml(XMLObj *obj) {
+ RGWXMLDecoder::decode_xml("Mode", mode, obj, true);
+ if (mode.compare("GOVERNANCE") != 0 && mode.compare("COMPLIANCE") != 0) {
+ throw RGWXMLDecoder::err("bad Mode in retention");
+ }
+ string date_str;
+ RGWXMLDecoder::decode_xml("RetainUntilDate", date_str, obj, true);
+ boost::optional<ceph::real_time> date = ceph::from_iso_8601(date_str);
+ if (boost::none == date) {
+ throw RGWXMLDecoder::err("invalid RetainUntilDate value");
+ }
+ retain_until_date = *date;
+}
+
+void RGWObjectRetention::dump_xml(Formatter *f) const {
+ encode_xml("Mode", mode, f);
+ string date = ceph::to_iso_8601(retain_until_date);
+ encode_xml("RetainUntilDate", date, f);
+}
+
+void RGWObjectLegalHold::decode_xml(XMLObj *obj) {
+ RGWXMLDecoder::decode_xml("Status", status, obj, true);
+ if (status.compare("ON") != 0 && status.compare("OFF") != 0) {
+ throw RGWXMLDecoder::err("bad status in legal hold");
+ }
+}
+
+void RGWObjectLegalHold::dump_xml(Formatter *f) const {
+ encode_xml("Status", status, f);
+}
+
+bool RGWObjectLegalHold::is_enabled() const {
+ return status.compare("ON") == 0;
+}
--- /dev/null
+#ifndef CEPH_RGW_OBJECT_LOCK_H
+#define CEPH_RGW_OBJECT_LOCK_H
+
+#include <string>
+#include "common/ceph_time.h"
+#include "common/iso_8601.h"
+#include "rgw_xml.h"
+using namespace std;
+
+class DefaultRetention
+{
+protected:
+ string mode;
+ int days;
+ int years;
+
+public:
+ DefaultRetention(): days(0), years(0) {};
+
+ int get_days() const {
+ return days;
+ }
+
+ int get_years() const {
+ return years;
+ }
+
+ string get_mode() const {
+ return mode;
+ }
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(mode, bl);
+ encode(days, bl);
+ encode(years, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(mode, bl);
+ decode(days, bl);
+ decode(years, bl);
+ DECODE_FINISH(bl);
+ }
+
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
+};
+WRITE_CLASS_ENCODER(DefaultRetention)
+
+class ObjectLockRule
+{
+protected:
+ DefaultRetention defaultRetention;
+public:
+ int get_days() const {
+ return defaultRetention.get_days();
+ }
+
+ int get_years() const {
+ return defaultRetention.get_years();
+ }
+
+ string get_mode() const {
+ return defaultRetention.get_mode();
+ }
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(defaultRetention, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(defaultRetention, bl);
+ DECODE_FINISH(bl);
+ }
+
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
+};
+WRITE_CLASS_ENCODER(ObjectLockRule)
+
+class RGWObjectLock
+{
+protected:
+ bool enabled;
+ bool rule_exist;
+ ObjectLockRule rule;
+
+public:
+ RGWObjectLock():enabled(true), rule_exist(false) {}
+
+ int get_days() const {
+ return rule.get_days();
+ }
+
+ int get_years() const {
+ return rule.get_years();
+ }
+
+ string get_mode() const {
+ return rule.get_mode();
+ }
+
+ bool retention_period_valid() const {
+ return (get_years() > 0 || get_days() > 0);
+ }
+
+ bool has_rule() const {
+ return rule_exist;
+ }
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(enabled, bl);
+ encode(rule_exist, bl);
+ if (rule_exist) {
+ encode(rule, bl);
+ }
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(enabled, bl);
+ decode(rule_exist, bl);
+ if (rule_exist) {
+ decode(rule, bl);
+ }
+ DECODE_FINISH(bl);
+ }
+
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
+ ceph::real_time get_lock_until_date(const ceph::real_time& mtime) const;
+};
+WRITE_CLASS_ENCODER(RGWObjectLock)
+
+class RGWObjectRetention
+{
+protected:
+ string mode;
+ ceph::real_time retain_until_date;
+public:
+ RGWObjectRetention() {}
+ RGWObjectRetention(string _mode, ceph::real_time _date): mode(_mode), retain_until_date(_date) {}
+
+ void set_mode(string _mode) {
+ mode = _mode;
+ }
+
+ string get_mode() const {
+ return mode;
+ }
+
+ void set_retain_until_date(ceph::real_time _retain_until_date) {
+ retain_until_date = _retain_until_date;
+ }
+
+ ceph::real_time get_retain_until_date() const {
+ return retain_until_date;
+ }
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(mode, bl);
+ encode(retain_until_date, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(mode, bl);
+ decode(retain_until_date, bl);
+ DECODE_FINISH(bl);
+ }
+
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
+};
+WRITE_CLASS_ENCODER(RGWObjectRetention)
+
+class RGWObjectLegalHold
+{
+protected:
+ string status;
+public:
+ void set_status(string _status) {
+ status = _status;
+ }
+
+ string get_status() const {
+ return status;
+ }
+
+ void encode(bufferlist& bl) const {
+ ENCODE_START(1, 1, bl);
+ encode(status, bl);
+ ENCODE_FINISH(bl);
+ }
+
+ void decode(bufferlist::const_iterator& bl) {
+ DECODE_START(1, bl);
+ decode(status, bl);
+ DECODE_FINISH(bl);
+ }
+
+ void decode_xml(XMLObj *obj);
+ void dump_xml(Formatter *f) const;
+ bool is_enabled() const;
+};
+WRITE_CLASS_ENCODER(RGWObjectLegalHold)
+#endif //CEPH_RGW_OBJECT_LOCK_H
return -EACCES;
}
+ if (s->bucket_info.obj_lock_enabled()) {
+ get_retention = verify_object_permission(this, s, rgw::IAM::s3GetObjectRetention);
+ get_legal_hold = verify_object_permission(this, s, rgw::IAM::s3GetObjectLegalHold);
+ }
+
return 0;
}
if (op_ret < 0)
return;
+ if (s->bucket_info.obj_lock_enabled() && versioning_status != VersioningEnabled) {
+ op_ret = -ERR_INVALID_BUCKET_STATE;
+ return;
+ }
+
bool cur_mfa_status = (s->bucket_info.flags & BUCKET_MFA_ENABLED) != 0;
mfa_set_status &= (mfa_status != cur_mfa_status);
s->bucket_info.swift_ver_location = *swift_ver_location;
s->bucket_info.swift_versioning = (! swift_ver_location->empty());
}
+ if (obj_lock_enabled) {
+ info.flags = BUCKET_VERSIONED | BUCKET_OBJ_LOCK_ENABLED;
+ }
+
op_ret = store->create_bucket(*(s->user), s->bucket, zonegroup_id,
placement_rule, s->bucket_info.swift_ver_location,
int RGWDeleteObj::verify_permission()
{
+ int op_ret = get_params();
+ if (op_ret) {
+ return op_ret;
+ }
if (s->iam_policy || ! s->iam_user_policies.empty()) {
+ if (s->bucket_info.obj_lock_enabled() && bypass_governance_mode) {
+ auto r = eval_user_policies(s->iam_user_policies, s->env, boost::none,
+ rgw::IAM::s3BypassGovernanceRetention, ARN(s->bucket, s->object.name));
+ if (r == Effect::Allow) {
+ bypass_perm = true;
+ } else if (r == Effect::Pass && s->iam_policy) {
+ r = s->iam_policy->eval(s->env, *s->auth.identity, rgw::IAM::s3BypassGovernanceRetention,
+ ARN(s->bucket, s->object.name));
+ if (r == Effect::Allow) {
+ bypass_perm = true;
+ }
+ }
+ }
auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
boost::none,
s->object.instance.empty() ?
return;
}
- op_ret = get_params();
- if (op_ret < 0) {
- return;
- }
-
rgw_obj obj(s->bucket, s->object);
map<string, bufferlist> attrs;
+ bool check_obj_lock = obj.key.have_instance() && s->bucket_info.obj_lock_enabled();
if (!s->object.empty()) {
- if (need_object_expiration() || multipart_delete) {
+ if (need_object_expiration() || multipart_delete || check_obj_lock) {
/* check if obj exists, read orig attrs */
op_ret = get_obj_attrs(store, s, obj, attrs);
if (op_ret < 0) {
}
}
+ if (check_obj_lock) {
+ auto aiter = attrs.find(RGW_ATTR_OBJECT_RETENTION);
+ if (aiter != attrs.end()) {
+ RGWObjectRetention obj_retention;
+ decode(obj_retention, aiter->second);
+ if (ceph::real_clock::to_time_t(obj_retention.get_retain_until_date()) > ceph_clock_now()) {
+ if (obj_retention.get_mode().compare("GOVERNANCE") != 0 || !bypass_perm || !bypass_governance_mode) {
+ op_ret = -EACCES;
+ return;
+ }
+ }
+ }
+ aiter = attrs.find(RGW_ATTR_OBJECT_LEGAL_HOLD);
+ if (aiter != attrs.end()) {
+ RGWObjectLegalHold obj_legal_hold;
+ decode(obj_legal_hold, aiter->second);
+ if (obj_legal_hold.is_enabled()) {
+ op_ret = -EACCES;
+ return;
+ }
+ }
+ }
+
if (multipart_delete) {
const auto slo_attr = attrs.find(RGW_ATTR_SLO_MANIFEST);
});
}
+void RGWPutBucketObjectLock::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+int RGWPutBucketObjectLock::verify_permission()
+{
+ return verify_bucket_owner_or_policy(s, rgw::IAM::s3PutBucketObjectLockConfiguration);
+}
+
+void RGWPutBucketObjectLock::execute()
+{
+ if (!s->bucket_info.obj_lock_enabled()) {
+ ldpp_dout(this, 0) << "ERROR: object Lock configuration cannot be enabled on existing buckets" << dendl;
+ op_ret = -ERR_INVALID_BUCKET_STATE;
+ return;
+ }
+
+ RGWXMLDecoder::XMLParser parser;
+ if (!parser.init()) {
+ ldpp_dout(this, 0) << "ERROR: failed to initialize parser" << dendl;
+ op_ret = -EINVAL;
+ return;
+ }
+
+ op_ret = get_params();
+ if (op_ret < 0)
+ return;
+
+ if (!parser.parse(data.c_str(), data.length(), 1)) {
+ op_ret = -ERR_MALFORMED_XML;
+ return;
+ }
+
+ try {
+ RGWXMLDecoder::decode_xml("ObjectLockConfiguration", obj_lock, &parser, true);
+ } catch (RGWXMLDecoder::err& err) {
+ ldout(s->cct, 5) << "unexpected xml:" << err.message << dendl;
+ op_ret = -ERR_MALFORMED_XML;
+ return;
+ }
+ if (obj_lock.has_rule() && !obj_lock.retention_period_valid()) {
+ ldpp_dout(this, 0) << "ERROR: retention period must be a positive integer value" << dendl;
+ op_ret = -EINVAL;
+ return;
+ }
+
+ if (!store->svc.zone->is_meta_master()) {
+ op_ret = forward_request_to_master(s, NULL, store, data, nullptr);
+ if (op_ret < 0) {
+ ldout(s->cct, 20) << __func__ << "forward_request_to_master returned ret=" << op_ret << dendl;
+ return;
+ }
+ }
+
+ op_ret = retry_raced_bucket_write(store, s, [this] {
+ s->bucket_info.obj_lock = obj_lock;
+ op_ret = store->put_bucket_instance_info(s->bucket_info, false,
+ real_time(), &s->bucket_attrs);
+ return op_ret;
+ });
+ return;
+}
+
+void RGWGetBucketObjectLock::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+int RGWGetBucketObjectLock::verify_permission()
+{
+ return verify_bucket_owner_or_policy(s, rgw::IAM::s3GetBucketObjectLockConfiguration);
+}
+
+void RGWGetBucketObjectLock::execute()
+{
+ if (!s->bucket_info.obj_lock_enabled()) {
+ op_ret = -ERR_NO_SUCH_OBJECT_LOCK_CONFIGURATION;
+ return;
+ }
+}
+
+int RGWPutObjRetention::verify_permission()
+{
+ if (!verify_object_permission(this, s, rgw::IAM::s3PutObjectRetention)) {
+ return -EACCES;
+ }
+ op_ret = get_params();
+ if (op_ret) {
+ return op_ret;
+ }
+ if (bypass_governance_mode) {
+ bypass_perm = verify_object_permission(this, s, rgw::IAM::s3BypassGovernanceRetention);
+ }
+ return 0;
+}
+
+void RGWPutObjRetention::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+void RGWPutObjRetention::execute()
+{
+ if (!s->bucket_info.obj_lock_enabled()) {
+ ldpp_dout(this, 0) << "ERROR: object retention can't be set if bucket object lock not configured" << dendl;
+ op_ret = -ERR_INVALID_REQUEST;
+ return;
+ }
+
+ RGWXMLDecoder::XMLParser parser;
+ if (!parser.init()) {
+ ldpp_dout(this, 0) << "ERROR: failed to initialize parser" << dendl;
+ op_ret = -EINVAL;
+ return;
+ }
+
+ op_ret = get_params();
+ if (op_ret < 0)
+ return;
+
+ if (!parser.parse(data.c_str(), data.length(), 1)) {
+ op_ret = -ERR_MALFORMED_XML;
+ return;
+ }
+
+ try {
+ RGWXMLDecoder::decode_xml("Retention", obj_retention, &parser, true);
+ } catch (RGWXMLDecoder::err& err) {
+ ldpp_dout(this, 5) << "unexpected xml:" << err.message << dendl;
+ op_ret = -ERR_MALFORMED_XML;
+ return;
+ }
+ bufferlist bl;
+ obj_retention.encode(bl);
+ rgw_obj obj(s->bucket, s->object);
+
+ //check old retention
+ map<string, bufferlist> attrs;
+ op_ret = get_obj_attrs(store, s, obj, attrs);
+ if (op_ret < 0) {
+ ldpp_dout(this, 0) << "ERROR: get obj attr error"<< dendl;
+ return;
+ }
+ auto aiter = attrs.find(RGW_ATTR_OBJECT_RETENTION);
+ if (aiter != attrs.end()) {
+ RGWObjectRetention old_obj_retention;
+ decode(old_obj_retention, aiter->second);
+ if (obj_retention.get_mode().compare("GOVERNANCE") != 0 || !bypass_perm || !bypass_governance_mode) {
+ op_ret = -EACCES;
+ return;
+ }
+ }
+
+ store->set_atomic(s->obj_ctx, obj);
+ attrs[RGW_ATTR_OBJECT_RETENTION] = bl;
+ op_ret = store->set_attrs(s->obj_ctx, s->bucket_info, obj, attrs, NULL);
+ return;
+}
+
+int RGWGetObjRetention::verify_permission()
+{
+ if (!verify_object_permission(this, s, rgw::IAM::s3GetObjectRetention)) {
+ return -EACCES;
+ }
+ return 0;
+}
+
+void RGWGetObjRetention::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+void RGWGetObjRetention::execute()
+{
+ if (!s->bucket_info.obj_lock_enabled()) {
+ ldpp_dout(this, 0) << "ERROR: bucket object lock not configured" << dendl;
+ op_ret = -ERR_INVALID_REQUEST;
+ return;
+ }
+ rgw_obj obj(s->bucket, s->object);
+ map<string, bufferlist> attrs;
+ op_ret = get_obj_attrs(store, s, obj, attrs);
+ if (op_ret < 0) {
+ ldpp_dout(this, 0) << "ERROR: failed to get obj attrs, obj=" << obj
+ << " ret=" << op_ret << dendl;
+ return;
+ }
+ auto aiter = attrs.find(RGW_ATTR_OBJECT_RETENTION);
+ if (aiter == attrs.end()) {
+ op_ret = -ERR_NO_SUCH_OBJECT_LOCK_CONFIGURATION;
+ return;
+ }
+
+ bufferlist::const_iterator iter{&aiter->second};
+ try {
+ obj_retention.decode(iter);
+ } catch (const buffer::error& e) {
+ ldout(s->cct, 0) << __func__ << "decode object retention config failed" << dendl;
+ op_ret = -EIO;
+ return;
+ }
+ return;
+}
+
+int RGWPutObjLegalHold::verify_permission()
+{
+ if (!verify_object_permission(this, s, rgw::IAM::s3PutObjectLegalHold)) {
+ return -EACCES;
+ }
+ return 0;
+}
+
+void RGWPutObjLegalHold::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+void RGWPutObjLegalHold::execute() {
+ if (!s->bucket_info.obj_lock_enabled()) {
+ ldpp_dout(this, 0) << "ERROR: object legal hold can't be set if bucket object lock not configured" << dendl;
+ op_ret = -ERR_INVALID_REQUEST;
+ return;
+ }
+
+ RGWXMLDecoder::XMLParser parser;
+ if (!parser.init()) {
+ ldpp_dout(this, 0) << "ERROR: failed to initialize parser" << dendl;
+ op_ret = -EINVAL;
+ return;
+ }
+
+ op_ret = get_params();
+ if (op_ret < 0)
+ return;
+
+ if (!parser.parse(data.c_str(), data.length(), 1)) {
+ op_ret = -ERR_MALFORMED_XML;
+ return;
+ }
+
+ try {
+ RGWXMLDecoder::decode_xml("LegalHold", obj_legal_hold, &parser, true);
+ } catch (RGWXMLDecoder::err &err) {
+ ldout(s->cct, 5) << "unexpected xml:" << err.message << dendl;
+ op_ret = -ERR_MALFORMED_XML;
+ return;
+ }
+ bufferlist bl;
+ obj_legal_hold.encode(bl);
+ rgw_obj obj(s->bucket, s->object);
+ store->set_atomic(s->obj_ctx, obj);
+ //if instance is empty, we should modify the latest object
+ op_ret = modify_obj_attr(store, s, obj, RGW_ATTR_OBJECT_LEGAL_HOLD, bl);
+ return;
+}
+
+int RGWGetObjLegalHold::verify_permission()
+{
+ if (!verify_object_permission(this, s, rgw::IAM::s3GetObjectLegalHold)) {
+ return -EACCES;
+ }
+ return 0;
+}
+
+void RGWGetObjLegalHold::pre_exec()
+{
+ rgw_bucket_object_pre_exec(s);
+}
+
+void RGWGetObjLegalHold::execute()
+{
+ if (!s->bucket_info.obj_lock_enabled()) {
+ ldpp_dout(this, 0) << "ERROR: bucket object lock not configured" << dendl;
+ op_ret = -ERR_INVALID_REQUEST;
+ return;
+ }
+ rgw_obj obj(s->bucket, s->object);
+ map<string, bufferlist> attrs;
+ op_ret = get_obj_attrs(store, s, obj, attrs);
+ if (op_ret < 0) {
+ ldpp_dout(this, 0) << "ERROR: failed to get obj attrs, obj=" << obj
+ << " ret=" << op_ret << dendl;
+ return;
+ }
+ auto aiter = attrs.find(RGW_ATTR_OBJECT_LEGAL_HOLD);
+ if (aiter == attrs.end()) {
+ op_ret = -ERR_NO_SUCH_OBJECT_LOCK_CONFIGURATION;
+ return;
+ }
+
+ bufferlist::const_iterator iter{&aiter->second};
+ try {
+ obj_legal_hold.decode(iter);
+ } catch (const buffer::error& e) {
+ ldout(s->cct, 0) << __func__ << "decode object legal hold config failed" << dendl;
+ op_ret = -EIO;
+ return;
+ }
+ return;
+}
+
void RGWGetClusterStat::execute()
{
op_ret = this->store->get_rados_handle()->cluster_stat(stats_op);
#include "rgw_lc.h"
#include "rgw_torrent.h"
#include "rgw_tag.h"
+#include "rgw_object_lock.h"
#include "cls/lock/cls_lock_client.h"
#include "cls/rgw/cls_rgw_client.h"
bufferlist waiting;
uint64_t action = 0;
+ bool get_retention;
+ bool get_legal_hold;
+
int init_common();
public:
RGWGetObj() {
q_len = 0;
first_data = true;
cur_ofs = 0;
+ get_retention = false;
+ get_legal_hold = false;
}
bool prefetch_data() override;
obj_version ep_objv;
bool has_cors;
bool relaxed_region_enforcement;
+ bool obj_lock_enabled;
RGWCORSConfiguration cors_config;
boost::optional<std::string> swift_ver_location;
map<string, buffer::list> attrs;
virtual bool need_metadata_upload() const { return false; }
public:
- RGWCreateBucket() : has_cors(false), relaxed_region_enforcement(false) {}
+ RGWCreateBucket() : has_cors(false), relaxed_region_enforcement(false), obj_lock_enabled(false) {}
void emplace_attr(std::string&& key, buffer::list&& bl) {
attrs.emplace(std::move(key), std::move(bl)); /* key and bl are r-value refs */
ceph::real_time unmod_since; /* if unmodified since */
bool no_precondition_error;
std::unique_ptr<RGWBulkDelete::Deleter> deleter;
+ bool bypass_perm;
+ bool bypass_governance_mode;
public:
RGWDeleteObj()
: delete_marker(false),
multipart_delete(false),
no_precondition_error(false),
- deleter(nullptr) {
+ deleter(nullptr),
+ bypass_perm(false),
+ bypass_governance_mode(false) {
}
int verify_permission() override;
}
};
+class RGWPutBucketObjectLock : public RGWOp {
+protected:
+ bufferlist data;
+ bufferlist obj_lock_bl;
+ RGWObjectLock obj_lock;
+public:
+ RGWPutBucketObjectLock() = default;
+ ~RGWPutBucketObjectLock() {}
+ int verify_permission() override;
+ void pre_exec() override;
+ void execute() override;
+ virtual void send_response() = 0;
+ virtual int get_params() = 0;
+ const char* name() const override { return "put_bucket_object_lock"; }
+ RGWOpType get_type() override { return RGW_OP_PUT_BUCKET_OBJ_LOCK; }
+ uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
+};
+
+class RGWGetBucketObjectLock : public RGWOp {
+public:
+ int verify_permission() override;
+ void pre_exec() override;
+ void execute() override;
+ virtual void send_response() = 0;
+ const char* name() const override {return "get_bucket_object_lock"; }
+ RGWOpType get_type() override { return RGW_OP_GET_BUCKET_OBJ_LOCK; }
+ uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
+};
+
+class RGWPutObjRetention : public RGWOp {
+protected:
+ bufferlist data;
+ RGWObjectRetention obj_retention;
+ bool bypass_perm;
+ bool bypass_governance_mode;
+public:
+ int verify_permission() override;
+ void pre_exec() override;
+ void execute() override;
+ virtual void send_response() override = 0;
+ virtual int get_params() = 0;
+ const char* name() const override { return "put_obj_retention"; }
+ uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
+ RGWOpType get_type() override { return RGW_OP_PUT_OBJ_RETENTION; }
+};
+
+class RGWGetObjRetention : public RGWOp {
+protected:
+ RGWObjectRetention obj_retention;
+public:
+ int verify_permission() override;
+ void pre_exec() override;
+ void execute() override;
+ virtual void send_response() = 0;
+ const char* name() const override {return "get_obj_retention"; }
+ RGWOpType get_type() override { return RGW_OP_GET_OBJ_RETENTION; }
+ uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
+};
+
+class RGWPutObjLegalHold : public RGWOp {
+protected:
+ bufferlist data;
+ RGWObjectLegalHold obj_legal_hold;
+public:
+ int verify_permission() override;
+ void pre_exec() override;
+ void execute() override;
+ virtual void send_response() override = 0;
+ virtual int get_params() = 0;
+ const char* name() const override { return "put_obj_legal_hold"; }
+ uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
+ RGWOpType get_type() override { return RGW_OP_PUT_OBJ_LEGAL_HOLD; }
+};
+
+class RGWGetObjLegalHold : public RGWOp {
+protected:
+ RGWObjectLegalHold obj_legal_hold;
+public:
+ int verify_permission() override;
+ void pre_exec() override;
+ void execute() override;
+ virtual void send_response() = 0;
+ const char* name() const override {return "get_obj_legal_hold"; }
+ RGWOpType get_type() override { return RGW_OP_GET_OBJ_LEGAL_HOLD; }
+ uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
+};
+
class RGWConfigBucketMetaSearch : public RGWOp {
protected:
meta.set_mtime = real_clock::now();
}
+ if (target->bucket_info.obj_lock_enabled() && target->bucket_info.obj_lock.has_rule() && meta.flags == PUT_OBJ_CREATE) {
+ real_time lock_until_date = target->bucket_info.obj_lock.get_lock_until_date(meta.set_mtime);
+ string mode = target->bucket_info.obj_lock.get_mode();
+ RGWObjectRetention obj_retention(mode, lock_until_date);
+ bufferlist bl;
+ obj_retention.encode(bl);
+ op.setxattr(RGW_ATTR_OBJECT_RETENTION, bl);
+ }
+
if (state->is_olh) {
op.setxattr(RGW_ATTR_OLH_ID_TAG, state->olh_tag);
}
return op_ret;
}
+int RGWPutBucketObjectLock_ObjStore::get_params()
+{
+ const auto max_size = s->cct->_conf->rgw_max_put_param_size;
+ std::tie(op_ret, data) = rgw_rest_read_all_input(s, max_size, false);
+ return op_ret;
+}
+
+int RGWPutObjLegalHold_ObjStore::get_params()
+{
+ const auto max_size = s->cct->_conf->rgw_max_put_param_size;
+ std::tie(op_ret, data) = rgw_rest_read_all_input(s, max_size, false);
+ return op_ret;
+}
+
+
static std::tuple<int, bufferlist> read_all_chunked_input(req_state *s, const uint64_t max_read)
{
#define READ_CHUNK 4096
~RGWInfo_ObjStore() override = default;
};
+class RGWPutBucketObjectLock_ObjStore : public RGWPutBucketObjectLock {
+public:
+ RGWPutBucketObjectLock_ObjStore() = default;
+ ~RGWPutBucketObjectLock_ObjStore() = default;
+ int get_params() override;
+};
+
+class RGWGetBucketObjectLock_ObjStore : public RGWGetBucketObjectLock {
+public:
+ RGWGetBucketObjectLock_ObjStore() = default;
+ ~RGWGetBucketObjectLock_ObjStore() override = default;
+};
+
+class RGWPutObjRetention_ObjStore : public RGWPutObjRetention {
+public:
+ RGWPutObjRetention_ObjStore() = default;
+ ~RGWPutObjRetention_ObjStore() override = default;
+};
+
+class RGWGetObjRetention_ObjStore : public RGWGetObjRetention {
+public:
+ RGWGetObjRetention_ObjStore() = default;
+ ~RGWGetObjRetention_ObjStore() = default;
+};
+
+class RGWPutObjLegalHold_ObjStore : public RGWPutObjLegalHold {
+public:
+ RGWPutObjLegalHold_ObjStore() = default;
+ ~RGWPutObjLegalHold_ObjStore() override = default;
+ int get_params() override;
+};
+
+class RGWGetObjLegalHold_ObjStore : public RGWGetObjLegalHold {
+public:
+ RGWGetObjLegalHold_ObjStore() = default;
+ ~RGWGetObjLegalHold_ObjStore() = default;
+};
+
class RGWRESTOp : public RGWOp {
protected:
int http_ret;
} else {
dump_header(s, "x-rgw-object-type", "Normal");
}
+
if (! op_ret) {
if (! lo_etag.empty()) {
/* Handle etag of Swift API's large objects (DLO/SLO). It's entirerly
ldpp_dout(this,0) << "Error caught buffer::error couldn't decode TagSet " << dendl;
}
dump_header(s, RGW_AMZ_TAG_COUNT, obj_tags.count());
+ } else if (iter->first.compare(RGW_ATTR_OBJECT_LOCK_MODE) == 0 && get_retention) {
+ dump_header(s, "x-amz-object-lock-mode", iter->second.to_str());
+ } else if (iter->first.compare(RGW_ATTR_OBJECT_LOCK_UNTIL_DATE) == 0 && get_retention) {
+ real_time lock_until_date;
+ decode(lock_until_date, iter->second);
+ dump_time_header(s, "x-amz-object-lock-retain-until-date", lock_until_date);
}
}
}
} else {
placement_rule.storage_class = s->info.storage_class;
}
-
+ auto iter = s->info.x_meta_map.find("x-amz-bucket-object-lock-enabled");
+ if (iter != s->info.x_meta_map.end()) {
+ if ((iter->second.compare("true") != 0 && (iter->second.compare("false") != 0))) {
+ return -EINVAL;
+ }
+ obj_lock_enabled = iter->second.compare("true") == 0;
+ }
return 0;
}
unmod_since = utime_t(epoch, nsec).to_real_time();
}
+ const char *bypass_gov_header = s->info.env->get("HTTP_X_AMZ_BYPASS_GOVERNANCE_RETENTION");
+ if (bypass_gov_header) {
+ std::string bypass_gov_decoded = url_decode(bypass_gov_header);
+ bypass_governance_mode = bypass_gov_decoded.compare("true") == 0;
+ }
+
return 0;
}
end_header(s, this);
}
+void RGWPutBucketObjectLock_ObjStore_S3::send_response()
+{
+ if (op_ret) {
+ set_req_state_err(s, op_ret);
+ }
+ dump_errno(s);
+ end_header(s);
+}
+
+void RGWGetBucketObjectLock_ObjStore_S3::send_response()
+{
+ if (op_ret) {
+ set_req_state_err(s, op_ret);
+ }
+ dump_errno(s);
+ end_header(s, this, "application/xml");
+ dump_start(s);
+
+ if (op_ret) {
+ return;
+ }
+ encode_xml("ObjectLockConfiguration", s->bucket_info.obj_lock, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
+}
+
+
+int RGWPutObjRetention_ObjStore_S3::get_params()
+{
+ const char *bypass_gov_header = s->info.env->get("HTTP_X_AMZ_BYPASS_GOVERNANCE_RETENTION");
+ if (bypass_gov_header) {
+ std::string bypass_gov_decoded = url_decode(bypass_gov_header);
+ bypass_governance_mode = bypass_gov_decoded.compare("true") == 0;
+ }
+
+ const auto max_size = s->cct->_conf->rgw_max_put_param_size;
+ std::tie(op_ret, data) = rgw_rest_read_all_input(s, max_size, false);
+ return op_ret;
+}
+
+void RGWPutObjRetention_ObjStore_S3::send_response()
+{
+ if (op_ret) {
+ set_req_state_err(s, op_ret);
+ }
+ dump_errno(s);
+ end_header(s);
+}
+
+void RGWGetObjRetention_ObjStore_S3::send_response()
+{
+ if (op_ret) {
+ set_req_state_err(s, op_ret);
+ }
+ dump_errno(s);
+ end_header(s, this, "application/xml");
+ dump_start(s);
+
+ if (op_ret) {
+ return;
+ }
+ encode_xml("Retention", obj_retention, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
+}
+
+void RGWPutObjLegalHold_ObjStore_S3::send_response()
+{
+ if (op_ret) {
+ set_req_state_err(s, op_ret);
+ }
+ dump_errno(s);
+ end_header(s);
+}
+
+void RGWGetObjLegalHold_ObjStore_S3::send_response()
+{
+ if (op_ret) {
+ set_req_state_err(s, op_ret);
+ }
+ dump_errno(s);
+ end_header(s, this, "application/xml");
+ dump_start(s);
+
+ if (op_ret) {
+ return;
+ }
+ encode_xml("LegalHold", obj_legal_hold, s->formatter);
+ rgw_flush_formatter_and_reset(s, s->formatter);
+}
+
RGWOp *RGWHandler_REST_Service_S3::op_get()
{
return new RGWGetBucketPolicy;
} else if (is_tagging_op()) {
return new RGWGetBucketTags_ObjStore_S3;
- }
+ } else if (is_object_lock_op()) {
+ return new RGWGetBucketObjectLock_ObjStore_S3;
+ }
return get_obj_op(true);
}
return new RGWPutLC_ObjStore_S3;
} else if(is_policy_op()) {
return new RGWPutBucketPolicy;
+ } else if (is_tagging_op()) {
+ return nullptr;
+ } else if (is_object_lock_op()) {
+ return new RGWPutBucketObjectLock_ObjStore_S3;
}
return new RGWCreateBucket_ObjStore_S3;
}
return new RGWGetObjLayout_ObjStore_S3;
} else if (is_tagging_op()) {
return new RGWGetObjTags_ObjStore_S3;
+ } else if (is_obj_retention_op()) {
+ return new RGWGetObjRetention_ObjStore_S3;
+ } else if (is_obj_legal_hold_op()) {
+ return new RGWGetObjLegalHold_ObjStore_S3;
}
return get_obj_op(true);
}
return new RGWPutACLs_ObjStore_S3;
} else if (is_tagging_op()) {
return new RGWPutObjTags_ObjStore_S3;
+ } else if (is_obj_retention_op()) {
+ return new RGWPutObjRetention_ObjStore_S3;
+ } else if (is_obj_legal_hold_op()) {
+ return new RGWPutObjLegalHold_ObjStore_S3;
}
if (s->init_state.src_bucket.empty())
case RGW_OP_PUT_LC:
case RGW_OP_SET_REQUEST_PAYMENT:
case RGW_OP_PUBSUB_NOTIF_CREATE:
+ case RGW_OP_PUT_BUCKET_OBJ_LOCK:
+ case RGW_OP_PUT_OBJ_RETENTION:
+ case RGW_OP_PUT_OBJ_LEGAL_HOLD:
+ case RGW_STS_GET_SESSION_TOKEN:
+ case RGW_STS_ASSUME_ROLE:
break;
default:
dout(10) << "ERROR: AWS4 completion for this operation NOT IMPLEMENTED" << dendl;
void end_response() override;
};
+class RGWPutBucketObjectLock_ObjStore_S3 : public RGWPutBucketObjectLock_ObjStore {
+public:
+ RGWPutBucketObjectLock_ObjStore_S3() {}
+ ~RGWPutBucketObjectLock_ObjStore_S3() override {}
+ void send_response() override;
+};
+
+class RGWGetBucketObjectLock_ObjStore_S3 : public RGWGetBucketObjectLock_ObjStore {
+public:
+ RGWGetBucketObjectLock_ObjStore_S3() {}
+ ~RGWGetBucketObjectLock_ObjStore_S3() {}
+ void send_response() override;
+};
+
+class RGWPutObjRetention_ObjStore_S3 : public RGWPutObjRetention_ObjStore {
+public:
+ RGWPutObjRetention_ObjStore_S3() {}
+ ~RGWPutObjRetention_ObjStore_S3() {}
+ int get_params() override;
+ void send_response() override;
+};
+
+class RGWGetObjRetention_ObjStore_S3 : public RGWGetObjRetention_ObjStore {
+public:
+ RGWGetObjRetention_ObjStore_S3() {}
+ ~RGWGetObjRetention_ObjStore_S3() {}
+ void send_response() override;
+};
+
+class RGWPutObjLegalHold_ObjStore_S3 : public RGWPutObjLegalHold_ObjStore {
+public:
+ RGWPutObjLegalHold_ObjStore_S3() {}
+ ~RGWPutObjLegalHold_ObjStore_S3() {}
+ void send_response() override;
+};
+
+class RGWGetObjLegalHold_ObjStore_S3 : public RGWGetObjLegalHold_ObjStore {
+public:
+ RGWGetObjLegalHold_ObjStore_S3() {}
+ ~RGWGetObjLegalHold_ObjStore_S3() {}
+ void send_response() override;
+};
+
class RGWGetObjLayout_ObjStore_S3 : public RGWGetObjLayout {
public:
RGWGetObjLayout_ObjStore_S3() {}
return s->info.args.exists("policy");
}
bool is_tagging_op() const {
- return s->info.args.exists("tagging");
+ return s->info.args.exists("tagging");
+ }
+ bool is_object_lock_op() {
+ return s->info.args.exists("object-lock");
}
RGWOp *get_obj_op(bool get_data);
bool is_tagging_op() {
return s->info.args.exists("tagging");
}
+ bool is_obj_retention_op() {
+ return s->info.args.exists("retention");
+ }
+ bool is_obj_legal_hold_op() {
+ return s->info.args.exists("legal-hold");
+ }
+
bool is_obj_update_op() override {
- return is_acl_op() || is_tagging_op() ;
+ return is_acl_op() || is_tagging_op() || is_obj_retention_op() || is_obj_legal_hold_op();
}
RGWOp *get_obj_op(bool get_data);