const rgw_user& bucket_owner = bucket_policy.get_owner().get_id();
if (bucket_owner.compare(s->user->get_id()) != 0 &&
! s->auth.identity->is_admin_of(bucket_owner)) {
+ auto r = eval_user_policies(s->iam_user_policies, s->env,
+ *s->auth.identity, rgw::IAM::s3ListBucket,
+ ARN(bucket));
+ if (r == Effect::Allow)
+ return -ENOENT;
+ if (r == Effect::Deny)
+ return -EACCES;
if (policy) {
- auto r = policy->eval(s->env, *s->auth.identity, rgw::IAM::s3ListBucket, ARN(bucket));
+ r = policy->eval(s->env, *s->auth.identity, rgw::IAM::s3ListBucket, ARN(bucket));
if (r == Effect::Allow)
return -ENOENT;
if (r == Effect::Deny)
}
}
-
int RGWGetObj::verify_permission()
{
obj = rgw_obj(s->bucket, s->object);
return true;
}
-int RGWGetObj::read_user_manifest_part(rgw_bucket& bucket,
+int RGWGetObj::read_user_manifest_part(RGWBucketInfo& bucket_info,
const rgw_bucket_dir_entry& ent,
RGWAccessControlPolicy * const bucket_acl,
const boost::optional<Policy>& bucket_policy,
int64_t cur_ofs = start_ofs;
int64_t cur_end = end_ofs;
+ rgw_bucket& bucket = bucket_info.bucket;
+
rgw_obj part(bucket, ent.key);
map<string, bufferlist> attrs;
obj_ctx.set_atomic(part);
store->getRados()->set_prefetch_data(&obj_ctx, part);
- RGWRados::Object op_target(store->getRados(), s->bucket_info, obj_ctx, part);
+ RGWRados::Object op_target(store->getRados(), bucket_info, obj_ctx, part);
RGWRados::Object::Read read_op(&op_target);
if (!swift_slo) {
uint64_t * const ptotal_len,
uint64_t * const pobj_size,
string * const pobj_sum,
- int (*cb)(rgw_bucket& bucket,
+ int (*cb)(RGWBucketInfo& bucket_info,
const rgw_bucket_dir_entry& ent,
RGWAccessControlPolicy * const bucket_acl,
const boost::optional<Policy>& bucket_policy,
len_count += end_ofs - start_ofs;
if (cb) {
- r = cb(bucket, ent, bucket_acl, bucket_policy, start_ofs, end_ofs,
+ r = cb(*pbucket_info, ent, bucket_acl, bucket_policy, start_ofs, end_ofs,
cb_param, false /* swift_slo */);
if (r < 0) {
return r;
struct rgw_slo_part {
RGWAccessControlPolicy *bucket_acl = nullptr;
Policy* bucket_policy = nullptr;
- rgw_bucket bucket;
+ RGWBucketInfo *pbucket_info = nullptr;
string obj_name;
uint64_t size = 0;
string etag;
off_t ofs,
off_t end,
map<uint64_t, rgw_slo_part>& slo_parts,
- int (*cb)(rgw_bucket& bucket,
+ int (*cb)(RGWBucketInfo& bucket_info,
const rgw_bucket_dir_entry& ent,
RGWAccessControlPolicy *bucket_acl,
const boost::optional<Policy>& bucket_policy,
<< dendl;
// SLO is a Swift thing, and Swift has no knowledge of S3 Policies.
- int r = cb(part.bucket, ent, part.bucket_acl,
+ int r = cb(*(part.pbucket_info), ent, part.bucket_acl,
(part.bucket_policy ?
boost::optional<Policy>(*part.bucket_policy) : none),
start_ofs, end_ofs, cb_param, true /* swift_slo */);
return 0;
}
-static int get_obj_user_manifest_iterate_cb(rgw_bucket& bucket,
+static int get_obj_user_manifest_iterate_cb(RGWBucketInfo& bucket_info,
const rgw_bucket_dir_entry& ent,
RGWAccessControlPolicy * const bucket_acl,
const boost::optional<Policy>& bucket_policy,
{
RGWGetObj *op = static_cast<RGWGetObj *>(param);
return op->read_user_manifest_part(
- bucket, ent, bucket_acl, bucket_policy, start_ofs, end_ofs, swift_slo);
+ bucket_info, ent, bucket_acl, bucket_policy, start_ofs, end_ofs, swift_slo);
}
int RGWGetObj::handle_user_manifest(const char *prefix)
vector<RGWAccessControlPolicy> allocated_acls;
map<string, pair<RGWAccessControlPolicy *, boost::optional<Policy>>> policies;
- map<string, rgw_bucket> buckets;
+ map<string, RGWBucketInfo> bucket_infos;
map<uint64_t, rgw_slo_part> slo_parts;
string obj_name = path.substr(pos_sep + 1);
rgw_bucket bucket;
+ RGWBucketInfo *pbucket_info;
RGWAccessControlPolicy *bucket_acl;
Policy* bucket_policy;
if (piter != policies.end()) {
bucket_acl = piter->second.first;
bucket_policy = piter->second.second.get_ptr();
- bucket = buckets[bucket_name];
+ pbucket_info = &bucket_infos[bucket_name];
} else {
allocated_acls.push_back(RGWAccessControlPolicy(s->cct));
RGWAccessControlPolicy& _bucket_acl = allocated_acls.back();
auto _bucket_policy = get_iam_policy_from_attr(
s->cct, store, bucket_attrs, bucket_info.bucket.tenant);
bucket_policy = _bucket_policy.get_ptr();
- buckets[bucket_name] = bucket;
+ bucket_infos.emplace(bucket_name, std::move(bucket_info));
+ pbucket_info = &bucket_infos[bucket_name];
policies[bucket_name] = make_pair(bucket_acl, _bucket_policy);
}
} else {
- bucket = s->bucket;
+ pbucket_info = &s->bucket_info;
bucket_acl = s->bucket_acl.get();
bucket_policy = s->iam_policy.get_ptr();
}
rgw_slo_part part;
part.bucket_acl = bucket_acl;
part.bucket_policy = bucket_policy;
- part.bucket = bucket;
+ part.pbucket_info = pbucket_info;
part.obj_name = obj_name;
part.size = entry.size_bytes;
part.etag = entry.etag;
- ldpp_dout(this, 20) << "slo_part: bucket=" << part.bucket
+ ldpp_dout(this, 20) << "slo_part: bucket=" << part.pbucket_info->bucket
<< " obj=" << part.obj_name
<< " size=" << part.size
<< " etag=" << part.etag
bool is_truncated = true;
RGWUsageIter usage_iter;
-
+
while (is_truncated) {
op_ret = store->getRados()->read_usage(s->user->get_id(), s->bucket_name, start_epoch, end_epoch, max_entries,
&is_truncated, usage_iter, usage);
-
if (op_ret == -ENOENT) {
op_ret = 0;
is_truncated = false;
return;
if (s->bucket_info.obj_lock_enabled() && versioning_status != VersioningEnabled) {
+ s->err.message = "bucket versioning cannot be disabled on buckets with object lock enabled";
+ ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl;
op_ret = -ERR_INVALID_BUCKET_STATE;
return;
}
filter = decrypt.get();
}
if (op_ret < 0) {
- return ret;
+ return op_ret;
}
ret = read_op.range_to_ofs(obj_size, new_ofs, new_end);
op_ret = 0;
if (check_obj_lock) {
- auto aiter = attrs.find(RGW_ATTR_OBJECT_RETENTION);
- if (aiter != attrs.end()) {
- RGWObjectRetention obj_retention;
- try {
- decode(obj_retention, aiter->second);
- } catch (buffer::error& err) {
- ldpp_dout(this, 0) << "ERROR: failed to decode RGWObjectRetention" << dendl;
- op_ret = -EIO;
- return;
- }
- 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;
- try {
- decode(obj_legal_hold, aiter->second);
- } catch (buffer::error& err) {
- ldpp_dout(this, 0) << "ERROR: failed to decode RGWObjectLegalHold" << dendl;
- op_ret = -EIO;
- return;
- }
- if (obj_legal_hold.is_enabled()) {
- op_ret = -EACCES;
- return;
- }
+ int object_lock_response = verify_object_lock(this, attrs, bypass_perm, bypass_governance_mode);
+ if (object_lock_response != 0) {
+ op_ret = object_lock_response;
+ return;
}
}
int RGWDeleteMultiObj::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_info.bucket));
+ if (r == Effect::Deny) {
+ bypass_perm = false;
+ } else if (r == Effect::Pass && s->iam_policy) {
+ r = s->iam_policy->eval(s->env, *s->auth.identity, rgw::IAM::s3BypassGovernanceRetention,
+ ARN(s->bucket_info.bucket));
+ if (r == Effect::Deny) {
+ bypass_perm = false;
+ }
+ }
+ }
+
+ bool not_versioned = s->object.empty() || s->object.instance.empty();
+
auto usr_policy_res = eval_user_policies(s->iam_user_policies, s->env,
boost::none,
- s->object.instance.empty() ?
+ not_versioned ?
rgw::IAM::s3DeleteObject :
rgw::IAM::s3DeleteObjectVersion,
ARN(s->bucket));
rgw::IAM::Effect r = Effect::Pass;
if (s->iam_policy) {
r = s->iam_policy->eval(s->env, *s->auth.identity,
- s->object.instance.empty() ?
+ not_versioned ?
rgw::IAM::s3DeleteObject :
rgw::IAM::s3DeleteObjectVersion,
ARN(s->bucket));
RGWObjectCtx *obj_ctx = static_cast<RGWObjectCtx *>(s->obj_ctx);
char* buf;
- op_ret = get_params();
- if (op_ret < 0) {
- goto error;
- }
-
buf = data.c_str();
if (!buf) {
op_ret = -EINVAL;
}
}
+ // verify_object_lock
+ bool check_obj_lock = obj.key.have_instance() && s->bucket_info.obj_lock_enabled();
+ map<string,bufferlist> attrs;
+ if (check_obj_lock) {
+ int get_attrs_response = get_obj_attrs(store, s, obj, attrs);
+ if (get_attrs_response < 0) {
+ if (get_attrs_response == -ENOENT) {
+ // object maybe delete_marker, skip check_obj_lock
+ check_obj_lock = false;
+ } else {
+ // Something went wrong.
+ send_partial_response(*iter, false, "", get_attrs_response);
+ continue;
+ }
+ }
+ }
+
+ if (check_obj_lock) {
+ int object_lock_response = verify_object_lock(this, attrs, bypass_perm, bypass_governance_mode);
+ if (object_lock_response != 0) {
+ send_partial_response(*iter, false, "", object_lock_response);
+ continue;
+ }
+ }
+
obj_ctx->set_atomic(obj);
RGWRados::Object del_target(store->getRados(), s->bucket_info, *obj_ctx, obj);
void RGWPutBucketPolicy::send_response()
{
+ if (!op_ret) {
+ /* A successful Put Bucket Policy should return a 204 on success */
+ op_ret = STATUS_NO_CONTENT;
+ }
if (op_ret) {
set_req_state_err(s, op_ret);
}
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;
+ s->err.message = "object lock configuration can't be set if bucket object lock not enabled";
+ ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl;
op_ret = -ERR_INVALID_BUCKET_STATE;
return;
}
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;
+ s->err.message = "retention period must be a positive integer value";
+ ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl;
op_ret = -ERR_INVALID_RETENTION_PERIOD;
return;
}
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;
+ s->err.message = "object retention can't be set if bucket object lock not configured";
+ ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl;
op_ret = -ERR_INVALID_REQUEST;
return;
}
}
if (ceph::real_clock::to_time_t(obj_retention.get_retain_until_date()) < ceph_clock_now()) {
- ldpp_dout(this, 0) << "ERROR: the retain until date must be in the future" << dendl;
+ s->err.message = "the retain-until date must be in the future";
+ ldpp_dout(this, 0) << "ERROR: " << s->err.message << dendl;
op_ret = -EINVAL;
return;
}
}
if (ceph::real_clock::to_time_t(obj_retention.get_retain_until_date()) < ceph::real_clock::to_time_t(old_obj_retention.get_retain_until_date())) {
if (old_obj_retention.get_mode().compare("GOVERNANCE") != 0 || !bypass_perm || !bypass_governance_mode) {
+ s->err.message = "proposed retain-until date shortens an existing retention period and governance bypass check failed";
op_ret = -EACCES;
return;
}
void RGWGetObjRetention::execute()
{
if (!s->bucket_info.obj_lock_enabled()) {
- ldpp_dout(this, 0) << "ERROR: bucket object lock not configured" << dendl;
+ s->err.message = "bucket object lock not configured";
+ ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl;
op_ret = -ERR_INVALID_REQUEST;
return;
}
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;
+ s->err.message = "object legal hold can't be set if bucket object lock not enabled";
+ ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl;
op_ret = -ERR_INVALID_REQUEST;
return;
}
void RGWGetObjLegalHold::execute()
{
if (!s->bucket_info.obj_lock_enabled()) {
- ldpp_dout(this, 0) << "ERROR: bucket object lock not configured" << dendl;
+ s->err.message = "bucket object lock not configured";
+ ldpp_dout(this, 4) << "ERROR: " << s->err.message << dendl;
op_ret = -ERR_INVALID_REQUEST;
return;
}
op_ret = this->store->getRados()->get_rados_handle()->cluster_stat(stats_op);
}
-
int RGWGetBucketPolicyStatus::verify_permission()
{
if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketPolicyStatus)) {