mirror of
https://github.com/ceph/ceph
synced 2025-01-04 02:02:36 +00:00
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:
commit
b3cffa193d
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -28,6 +28,7 @@ static const auto signed_subresources = {
|
||||
"acl",
|
||||
"cors",
|
||||
"delete",
|
||||
"encryption",
|
||||
"lifecycle",
|
||||
"location",
|
||||
"logging",
|
||||
|
31
src/rgw/rgw_bucket_encryption.cc
Normal file
31
src/rgw/rgw_bucket_encryption.cc
Normal 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);
|
||||
}
|
130
src/rgw/rgw_bucket_encryption.h
Normal file
130
src/rgw/rgw_bucket_encryption.h
Normal 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)
|
@ -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({
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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() {}
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user