Merge pull request #42222 from flipkart-incubator/aws_sse_s3

rgw: Introduce BucketEncryption APIs to support SSE-S3 feature

Reviewed-by: Casey Bodley <cbodley@redhat.com>
This commit is contained in:
Casey Bodley 2021-07-27 10:52:23 -04:00 committed by GitHub
commit b3cffa193d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 474 additions and 2 deletions

View File

@ -43,6 +43,15 @@ integration with `Barbican`_, `Vault`_, and `KMIP`_ are implemented.
See `OpenStack Barbican Integration`_, `HashiCorp Vault Integration`_,
and `KMIP Integration`_.
Bucket Encryption APIs
======================
Bucket Encryption APIs to support server-side encryption with Amazon
S3-managed keys (SSE-S3) or AWS KMS customer master keys (SSE-KMS).
SSE-KMS implementation via BucketEncryption APIs is not supported yet.
See `PutBucketEncryption`_, `GetBucketEncryption`_, `DeleteBucketEncryption`_
Automatic Encryption (for testing only)
=======================================
@ -63,6 +72,9 @@ The configuration expects a base64-encoded 256 bit key. For example::
.. _Barbican: https://wiki.openstack.org/wiki/Barbican
.. _Vault: https://www.vaultproject.io/docs/
.. _KMIP: http://www.oasis-open.org/committees/kmip/
.. _PutBucketEncryption: https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketEncryption.html
.. _GetBucketEncryption: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketEncryption.html
.. _DeleteBucketEncryption: https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketEncryption.html
.. _OpenStack Barbican Integration: ../barbican
.. _HashiCorp Vault Integration: ../vault
.. _KMIP Integration: ../kmip

View File

@ -185,6 +185,8 @@ Internally, S3 operations are mapped to ACL permissions thus:
+---------------------------------------+---------------+
| ``s3:GetReplicationConfiguration`` | ``READ_ACP`` |
+---------------------------------------+---------------+
| ``s3:GetBucketEncryption`` | ``READ_ACP`` |
+---------------------------------------+---------------+
| ``s3:DeleteBucketPolicy`` | ``WRITE_ACP`` |
+---------------------------------------+---------------+
| ``s3:DeleteBucketWebsite`` | ``WRITE_ACP`` |
@ -219,6 +221,8 @@ Internally, S3 operations are mapped to ACL permissions thus:
+---------------------------------------+---------------+
| ``s3:PutReplicationConfiguration`` | ``WRITE_ACP`` |
+---------------------------------------+---------------+
| ``s3:PutBucketEncryption`` | ``WRITE_ACP`` |
+---------------------------------------+---------------+
Some mappings, (e.g. ``s3:CreateBucket`` to ``WRITE``) are not
applicable to S3 operation, but are required to allow Swift and S3 to

View File

@ -155,7 +155,8 @@ set(librgw_common_srcs
cls_fifo_legacy.cc
rgw_lua_utils.cc
rgw_lua.cc
rgw_lua_request.cc)
rgw_lua_request.cc
rgw_bucket_encryption.cc)
if(WITH_RADOSGW_AMQP_ENDPOINT)
list(APPEND librgw_common_srcs rgw_amqp.cc)

View File

@ -28,6 +28,7 @@ static const auto signed_subresources = {
"acl",
"cors",
"delete",
"encryption",
"lifecycle",
"location",
"logging",

View File

@ -0,0 +1,31 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp
//
#include "rgw_bucket_encryption.h"
#include "rgw_xml.h"
void ApplyServerSideEncryptionByDefault::decode_xml(XMLObj *obj) {
RGWXMLDecoder::decode_xml("KMSMasterKeyID", kmsMasterKeyID, obj, false);
RGWXMLDecoder::decode_xml("SSEAlgorithm", sseAlgorithm, obj, false);
}
void ApplyServerSideEncryptionByDefault::dump_xml(Formatter *f) const {
encode_xml("SSEAlgorithm", sseAlgorithm, f);
}
void ServerSideEncryptionConfiguration::decode_xml(XMLObj *obj) {
RGWXMLDecoder::decode_xml("ApplyServerSideEncryptionByDefault", applyServerSideEncryptionByDefault, obj, true);
RGWXMLDecoder::decode_xml("BucketKeyEnabled", bucketKeyEnabled, obj, false);
}
void ServerSideEncryptionConfiguration::dump_xml(Formatter *f) const {
encode_xml("ApplyServerSideEncryptionByDefault", applyServerSideEncryptionByDefault, f);
}
void RGWBucketEncryptionConfig::decode_xml(XMLObj *obj) {
rule_exist = RGWXMLDecoder::decode_xml("Rule", rule, obj);
}
void RGWBucketEncryptionConfig::dump_xml(Formatter *f) const {
encode_xml("Rule", rule, f);
}

View File

@ -0,0 +1,130 @@
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp
#pragma once
#include <include/types.h>
class XMLObj;
class ApplyServerSideEncryptionByDefault
{
string kmsMasterKeyID;
string sseAlgorithm;
public:
ApplyServerSideEncryptionByDefault(): kmsMasterKeyID(""), sseAlgorithm("") {};
const string& kms_master_key_id() const {
return kmsMasterKeyID;
}
const string& sse_algorithm() const {
return sseAlgorithm;
}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
encode(kmsMasterKeyID, bl);
encode(sseAlgorithm, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::const_iterator& bl) {
DECODE_START(1, bl);
decode(kmsMasterKeyID, bl);
decode(sseAlgorithm, bl);
DECODE_FINISH(bl);
}
void decode_xml(XMLObj *obj);
void dump_xml(Formatter *f) const;
};
WRITE_CLASS_ENCODER(ApplyServerSideEncryptionByDefault)
class ServerSideEncryptionConfiguration
{
protected:
ApplyServerSideEncryptionByDefault applyServerSideEncryptionByDefault;
bool bucketKeyEnabled;
public:
ServerSideEncryptionConfiguration(): bucketKeyEnabled(false) {};
const string& kms_master_key_id() const {
return applyServerSideEncryptionByDefault.kms_master_key_id();
}
const string& sse_algorithm() const {
return applyServerSideEncryptionByDefault.sse_algorithm();
}
bool bucket_key_enabled() const {
return bucketKeyEnabled;
}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, bl);
encode(applyServerSideEncryptionByDefault, bl);
encode(bucketKeyEnabled, bl);
ENCODE_FINISH(bl);
}
void decode(bufferlist::const_iterator& bl) {
DECODE_START(1, bl);
decode(applyServerSideEncryptionByDefault, bl);
decode(bucketKeyEnabled, bl);
DECODE_FINISH(bl);
}
void decode_xml(XMLObj *obj);
void dump_xml(Formatter *f) const;
};
WRITE_CLASS_ENCODER(ServerSideEncryptionConfiguration)
class RGWBucketEncryptionConfig
{
protected:
bool rule_exist;
ServerSideEncryptionConfiguration rule;
public:
RGWBucketEncryptionConfig(): rule_exist(false) {}
const string& kms_master_key_id() const {
return rule.kms_master_key_id();
}
const string& sse_algorithm() const {
return rule.sse_algorithm();
}
bool bucket_key_enabled() const {
return rule.bucket_key_enabled();
}
bool has_rule() const {
return rule_exist;
}
void encode(bufferlist& bl) const {
ENCODE_START(1, 1, 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(rule_exist, bl);
if (rule_exist) {
decode(rule, bl);
}
DECODE_FINISH(bl);
}
void decode_xml(XMLObj *obj);
void dump_xml(Formatter *f) const;
};
WRITE_CLASS_ENCODER(RGWBucketEncryptionConfig)

View File

@ -127,6 +127,7 @@ rgw_http_errors rgw_http_s3_errors({
{ ERR_RATE_LIMITED, {503, "SlowDown"}},
{ ERR_ZERO_IN_URL, {400, "InvalidRequest" }},
{ ERR_NO_SUCH_TAG_SET, {404, "NoSuchTagSetError"}},
{ ERR_NO_SUCH_BUCKET_ENCRYPTION_CONFIGURATION, {404, "ServerSideEncryptionConfigurationNotFoundError"}},
});
rgw_http_errors rgw_http_swift_errors({

View File

@ -143,6 +143,11 @@ using ceph::crypto::MD5;
#define RGW_ATTR_CRYPT_CONTEXT RGW_ATTR_CRYPT_PREFIX "context"
#define RGW_ATTR_CRYPT_DATAKEY RGW_ATTR_CRYPT_PREFIX "datakey"
/* SSE-S3 Encryption Attributes */
#define RGW_ATTR_BUCKET_ENCRYPTION_PREFIX RGW_ATTR_PREFIX "sse-s3."
#define RGW_ATTR_BUCKET_ENCRYPTION_POLICY RGW_ATTR_BUCKET_ENCRYPTION_PREFIX "policy"
#define RGW_ATTR_BUCKET_ENCRYPTION_KEY_ID RGW_ATTR_BUCKET_ENCRYPTION_PREFIX "key-id"
#define RGW_FORMAT_PLAIN 0
#define RGW_FORMAT_XML 1
@ -230,6 +235,7 @@ using ceph::crypto::MD5;
#define ERR_NO_SUCH_CORS_CONFIGURATION 2045
#define ERR_NO_SUCH_OBJECT_LOCK_CONFIGURATION 2046
#define ERR_INVALID_RETENTION_PERIOD 2047
#define ERR_NO_SUCH_BUCKET_ENCRYPTION_CONFIGURATION 2048
#define ERR_USER_SUSPENDED 2100
#define ERR_INTERNAL_ERROR 2200
#define ERR_NOT_IMPLEMENTED 2201

View File

@ -79,6 +79,7 @@ static const actpair actpairs[] =
{ "s3:GetAccelerateConfiguration", s3GetAccelerateConfiguration },
{ "s3:GetBucketAcl", s3GetBucketAcl },
{ "s3:GetBucketCORS", s3GetBucketCORS },
{ "s3:GetBucketEncryption", s3GetBucketEncryption },
{ "s3:GetBucketLocation", s3GetBucketLocation },
{ "s3:GetBucketLogging", s3GetBucketLogging },
{ "s3:GetBucketNotification", s3GetBucketNotification },
@ -111,6 +112,7 @@ static const actpair actpairs[] =
{ "s3:PutAccelerateConfiguration", s3PutAccelerateConfiguration },
{ "s3:PutBucketAcl", s3PutBucketAcl },
{ "s3:PutBucketCORS", s3PutBucketCORS },
{ "s3:PutBucketEncryption", s3PutBucketEncryption },
{ "s3:PutBucketLogging", s3PutBucketLogging },
{ "s3:PutBucketNotification", s3PutBucketNotification },
{ "s3:PutBucketPolicy", s3PutBucketPolicy },
@ -1136,6 +1138,12 @@ const char* action_bit_string(uint64_t action) {
case s3PutBucketCORS:
return "s3:PutBucketCORS";
case s3GetBucketEncryption:
return "s3:GetBucketEncryption";
case s3PutBucketEncryption:
return "s3:PutBucketEncryption";
case s3GetBucketVersioning:
return "s3:GetBucketVersioning";

View File

@ -107,7 +107,9 @@ static constexpr std::uint64_t s3DeletePublicAccessBlock = 64;
static constexpr std::uint64_t s3GetBucketPublicAccessBlock = 65;
static constexpr std::uint64_t s3PutBucketPublicAccessBlock = 66;
static constexpr std::uint64_t s3DeleteBucketPublicAccessBlock = 67;
static constexpr std::uint64_t s3All = 68;
static constexpr std::uint64_t s3GetBucketEncryption = 68;
static constexpr std::uint64_t s3PutBucketEncryption = 69;
static constexpr std::uint64_t s3All = 70;
static constexpr std::uint64_t iamPutUserPolicy = s3All + 1;
static constexpr std::uint64_t iamGetUserPolicy = s3All + 2;
@ -197,6 +199,7 @@ inline int op_to_perm(std::uint64_t op) {
case s3GetAccelerateConfiguration:
case s3GetBucketAcl:
case s3GetBucketCORS:
case s3GetBucketEncryption:
case s3GetBucketLocation:
case s3GetBucketLogging:
case s3GetBucketNotification:
@ -220,6 +223,7 @@ inline int op_to_perm(std::uint64_t op) {
case s3PutAccelerateConfiguration:
case s3PutBucketAcl:
case s3PutBucketCORS:
case s3PutBucketEncryption:
case s3PutBucketLogging:
case s3PutBucketNotification:
case s3PutBucketPolicy:

View File

@ -8551,3 +8551,133 @@ void RGWDeleteBucketPublicAccessBlock::execute(optional_yield y)
return op_ret;
});
}
int RGWPutBucketEncryption::get_params(optional_yield y)
{
const auto max_size = s->cct->_conf->rgw_max_put_param_size;
std::tie(op_ret, data) = read_all_input(s, max_size, false);
return op_ret;
}
int RGWPutBucketEncryption::verify_permission(optional_yield y)
{
if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketEncryption)) {
return -EACCES;
}
return 0;
}
void RGWPutBucketEncryption::execute(optional_yield y)
{
RGWXMLDecoder::XMLParser parser;
if (!parser.init()) {
ldpp_dout(this, 0) << "ERROR: failed to initialize parser" << dendl;
op_ret = -EINVAL;
return;
}
op_ret = get_params(y);
if (op_ret < 0) {
return;
}
if (!parser.parse(data.c_str(), data.length(), 1)) {
ldpp_dout(this, 0) << "ERROR: malformed XML" << dendl;
op_ret = -ERR_MALFORMED_XML;
return;
}
try {
RGWXMLDecoder::decode_xml("ServerSideEncryptionConfiguration", bucket_encryption_conf, &parser, true);
} catch (RGWXMLDecoder::err& err) {
ldpp_dout(this, 5) << "unexpected xml:" << err << dendl;
op_ret = -ERR_MALFORMED_XML;
return;
}
if(bucket_encryption_conf.kms_master_key_id().compare("") != 0) {
ldpp_dout(this, 5) << "encryption not supported with sse-kms" << dendl;
op_ret = -ERR_NOT_IMPLEMENTED;
s->err.message = "SSE-KMS support is not provided";
return;
}
if(bucket_encryption_conf.sse_algorithm().compare("AES256") != 0) {
ldpp_dout(this, 5) << "only aes256 algorithm is supported for encryption" << dendl;
op_ret = -ERR_NOT_IMPLEMENTED;
s->err.message = "Encryption is supported only with AES256 algorithm";
return;
}
op_ret = store->forward_request_to_master(this, s->user.get(), nullptr, data, nullptr, s->info, y);
if (op_ret < 0) {
ldpp_dout(this, 20) << "forward_request_to_master returned ret=" << op_ret << dendl;
return;
}
bufferlist key_id_bl;
string bucket_owner_id = s->bucket->get_info().owner.id;
key_id_bl.append(bucket_owner_id.c_str(), bucket_owner_id.size() + 1);
bufferlist conf_bl;
bucket_encryption_conf.encode(conf_bl);
op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this, y, &conf_bl, &key_id_bl] {
rgw::sal::Attrs attrs = s->bucket->get_attrs();
attrs[RGW_ATTR_BUCKET_ENCRYPTION_POLICY] = conf_bl;
attrs[RGW_ATTR_BUCKET_ENCRYPTION_KEY_ID] = key_id_bl;
return s->bucket->set_instance_attrs(this, attrs, y);
});
}
int RGWGetBucketEncryption::verify_permission(optional_yield y)
{
if (!verify_bucket_permission(this, s, rgw::IAM::s3GetBucketEncryption)) {
return -EACCES;
}
return 0;
}
void RGWGetBucketEncryption::execute(optional_yield y)
{
const auto& attrs = s->bucket_attrs;
if (auto aiter = attrs.find(RGW_ATTR_BUCKET_ENCRYPTION_POLICY);
aiter == attrs.end()) {
ldpp_dout(this, 0) << "can't find BUCKET ENCRYPTION attr for bucket_name = " << s->bucket_name << dendl;
op_ret = -ENOENT;
s->err.message = "The server side encryption configuration was not found";
return;
} else {
bufferlist::const_iterator iter{&aiter->second};
try {
bucket_encryption_conf.decode(iter);
} catch (const buffer::error& e) {
ldpp_dout(this, 0) << __func__ << "decode bucket_encryption_conf failed" << dendl;
op_ret = -EIO;
return;
}
}
}
int RGWDeleteBucketEncryption::verify_permission(optional_yield y)
{
if (!verify_bucket_permission(this, s, rgw::IAM::s3PutBucketEncryption)) {
return -EACCES;
}
return 0;
}
void RGWDeleteBucketEncryption::execute(optional_yield y)
{
bufferlist data;
op_ret = store->forward_request_to_master(this, s->user.get(), nullptr, data, nullptr, s->info, y);
if (op_ret < 0) {
ldpp_dout(this, 0) << "forward_request_to_master returned ret=" << op_ret << dendl;
return;
}
op_ret = retry_raced_bucket_write(this, s->bucket.get(), [this, y] {
rgw::sal::Attrs attrs = s->bucket->get_attrs();
attrs.erase(RGW_ATTR_BUCKET_ENCRYPTION_POLICY);
attrs.erase(RGW_ATTR_BUCKET_ENCRYPTION_KEY_ID);
op_ret = s->bucket->set_instance_attrs(this, attrs, y);
return op_ret;
});
}

View File

@ -51,6 +51,7 @@
#include "rgw_object_lock.h"
#include "cls/rgw/cls_rgw_client.h"
#include "rgw_public_access.h"
#include "rgw_bucket_encryption.h"
#include "services/svc_sys_obj.h"
#include "services/svc_tier_rados.h"
@ -1736,6 +1737,50 @@ public:
uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
};
class RGWPutBucketEncryption : public RGWOp {
protected:
RGWBucketEncryptionConfig bucket_encryption_conf;
bufferlist data;
public:
RGWPutBucketEncryption() = default;
~RGWPutBucketEncryption() {}
int get_params(optional_yield y);
int verify_permission(optional_yield y) override;
void execute(optional_yield y) override;
const char* name() const override { return "put_bucket_encryption"; }
RGWOpType get_type() override { return RGW_OP_PUT_BUCKET_ENCRYPTION; }
uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
};
class RGWGetBucketEncryption : public RGWOp {
protected:
RGWBucketEncryptionConfig bucket_encryption_conf;
public:
RGWGetBucketEncryption() {}
int get_params(optional_yield y);
int verify_permission(optional_yield y) override;
void execute(optional_yield y) override;
const char* name() const override { return "get_bucket_encryption"; }
RGWOpType get_type() override { return RGW_OP_GET_BUCKET_ENCRYPTION; }
uint32_t op_mask() override { return RGW_OP_TYPE_READ; }
};
class RGWDeleteBucketEncryption : public RGWOp {
protected:
RGWBucketEncryptionConfig bucket_encryption_conf;
public:
RGWDeleteBucketEncryption() {}
int get_params(optional_yield y);
int verify_permission(optional_yield y) override;
void execute(optional_yield y) override;
const char* name() const override { return "delete_bucket_encryption"; }
RGWOpType get_type() override { return RGW_OP_DELETE_BUCKET_ENCRYPTION; }
uint32_t op_mask() override { return RGW_OP_TYPE_WRITE; }
};
class RGWGetRequestPayment : public RGWOp {
protected:
bool requester_pays;

View File

@ -33,6 +33,9 @@ enum RGWOpType {
RGW_OP_PUT_CORS,
RGW_OP_DELETE_CORS,
RGW_OP_OPTIONS_CORS,
RGW_OP_GET_BUCKET_ENCRYPTION,
RGW_OP_PUT_BUCKET_ENCRYPTION,
RGW_OP_DELETE_BUCKET_ENCRYPTION,
RGW_OP_GET_REQUEST_PAYMENT,
RGW_OP_SET_REQUEST_PAYMENT,
RGW_OP_INIT_MULTIPART,

View File

@ -399,6 +399,24 @@ public:
~RGWOptionsCORS_ObjStore() override {}
};
class RGWGetBucketEncryption_ObjStore : public RGWGetBucketEncryption {
public:
RGWGetBucketEncryption_ObjStore() {}
~RGWGetBucketEncryption_ObjStore() override {}
};
class RGWPutBucketEncryption_ObjStore : public RGWPutBucketEncryption {
public:
RGWPutBucketEncryption_ObjStore() {}
~RGWPutBucketEncryption_ObjStore() override {}
};
class RGWDeleteBucketEncryption_ObjStore : public RGWDeleteBucketEncryption {
public:
RGWDeleteBucketEncryption_ObjStore() {}
~RGWDeleteBucketEncryption_ObjStore() override {}
};
class RGWInitMultipart_ObjStore : public RGWInitMultipart {
public:
RGWInitMultipart_ObjStore() {}

View File

@ -3549,6 +3549,45 @@ void RGWOptionsCORS_ObjStore_S3::send_response()
end_header(s, NULL);
}
void RGWPutBucketEncryption_ObjStore_S3::send_response()
{
if (op_ret) {
set_req_state_err(s, op_ret);
}
dump_errno(s);
end_header(s);
}
void RGWGetBucketEncryption_ObjStore_S3::send_response()
{
if (op_ret) {
if (op_ret == -ENOENT)
set_req_state_err(s, ERR_NO_SUCH_BUCKET_ENCRYPTION_CONFIGURATION);
else
set_req_state_err(s, op_ret);
}
dump_errno(s);
end_header(s, this, "application/xml");
dump_start(s);
if (!op_ret) {
encode_xml("ServerSideEncryptionConfiguration", bucket_encryption_conf, s->formatter);
rgw_flush_formatter_and_reset(s, s->formatter);
}
}
void RGWDeleteBucketEncryption_ObjStore_S3::send_response()
{
if (op_ret == 0) {
op_ret = STATUS_NO_CONTENT;
}
set_req_state_err(s, op_ret);
dump_errno(s);
end_header(s);
}
void RGWGetRequestPayment_ObjStore_S3::send_response()
{
dump_errno(s);
@ -4345,6 +4384,8 @@ RGWOp *RGWHandler_REST_Bucket_S3::op_get()
return new RGWGetBucketPolicyStatus_ObjStore_S3;
} else if (is_block_public_access_op()) {
return new RGWGetBucketPublicAccessBlock_ObjStore_S3;
} else if (is_bucket_encryption_op()) {
return new RGWGetBucketEncryption_ObjStore_S3;
}
return get_obj_op(true);
}
@ -4398,6 +4439,8 @@ RGWOp *RGWHandler_REST_Bucket_S3::op_put()
return new RGWPutBucketReplication_ObjStore_S3;
} else if (is_block_public_access_op()) {
return new RGWPutBucketPublicAccessBlock_ObjStore_S3;
} else if (is_bucket_encryption_op()) {
return new RGWPutBucketEncryption_ObjStore_S3;
}
return new RGWCreateBucket_ObjStore_S3;
}
@ -4422,6 +4465,8 @@ RGWOp *RGWHandler_REST_Bucket_S3::op_delete()
return new RGWDeleteBucketReplication_ObjStore_S3;
} else if (is_block_public_access_op()) {
return new RGWDeleteBucketPublicAccessBlock;
} else if (is_bucket_encryption_op()) {
return new RGWDeleteBucketEncryption_ObjStore_S3;
}
if (s->info.args.sub_resource_exists("website")) {
@ -5470,6 +5515,9 @@ AWSGeneralAbstractor::get_auth_data_v4(const req_state* const s,
case RGW_OP_PUT_OBJ:
case RGW_OP_PUT_ACLS:
case RGW_OP_PUT_CORS:
case RGW_OP_PUT_BUCKET_ENCRYPTION:
case RGW_OP_GET_BUCKET_ENCRYPTION:
case RGW_OP_DELETE_BUCKET_ENCRYPTION:
case RGW_OP_INIT_MULTIPART: // in case that Init Multipart uses CHUNK encoding
case RGW_OP_COMPLETE_MULTIPART:
case RGW_OP_SET_BUCKET_VERSIONING:

View File

@ -420,6 +420,30 @@ public:
void send_response() override;
};
class RGWGetBucketEncryption_ObjStore_S3 : public RGWGetBucketEncryption_ObjStore {
public:
RGWGetBucketEncryption_ObjStore_S3() {}
~RGWGetBucketEncryption_ObjStore_S3() override {}
void send_response() override;
};
class RGWPutBucketEncryption_ObjStore_S3 : public RGWPutBucketEncryption_ObjStore {
public:
RGWPutBucketEncryption_ObjStore_S3() {}
~RGWPutBucketEncryption_ObjStore_S3() override {}
void send_response() override;
};
class RGWDeleteBucketEncryption_ObjStore_S3 : public RGWDeleteBucketEncryption_ObjStore {
public:
RGWDeleteBucketEncryption_ObjStore_S3() {}
~RGWDeleteBucketEncryption_ObjStore_S3() override {}
void send_response() override;
};
class RGWGetRequestPayment_ObjStore_S3 : public RGWGetRequestPayment {
public:
RGWGetRequestPayment_ObjStore_S3() {}
@ -700,6 +724,9 @@ protected:
bool is_block_public_access_op() {
return s->info.args.exists("publicAccessBlock");
}
bool is_bucket_encryption_op() {
return s->info.args.exists("encryption");
}
RGWOp *get_obj_op(bool get_data) const;
RGWOp *op_get() override;

View File

@ -56,6 +56,7 @@ using rgw::IAM::s3GetBucketNotification;
using rgw::IAM::s3GetBucketPolicy;
using rgw::IAM::s3GetBucketPolicyStatus;
using rgw::IAM::s3GetBucketPublicAccessBlock;
using rgw::IAM::s3GetBucketEncryption;
using rgw::IAM::s3GetBucketRequestPayment;
using rgw::IAM::s3GetBucketTagging;
using rgw::IAM::s3GetBucketVersioning;
@ -386,6 +387,7 @@ TEST_F(PolicyTest, Parse3) {
act2[s3GetBucketPolicyStatus] = 1;
act2[s3GetBucketPublicAccessBlock] = 1;
act2[s3GetPublicAccessBlock] = 1;
act2[s3GetBucketEncryption] = 1;
EXPECT_EQ(p->statements[2].action, act2);
EXPECT_EQ(p->statements[2].notaction, None);
@ -455,6 +457,7 @@ TEST_F(PolicyTest, Eval3) {
s3allow[s3GetBucketPolicyStatus] = 1;
s3allow[s3GetBucketPublicAccessBlock] = 1;
s3allow[s3GetPublicAccessBlock] = 1;
s3allow[s3GetBucketEncryption] = 1;
EXPECT_EQ(p.eval(em, none, s3PutBucketPolicy,
ARN(Partition::aws, Service::s3,