mirror of
https://github.com/ceph/ceph
synced 2025-04-01 14:51:13 +00:00
Merge pull request #16612 from cbodley/wip-20668
rgw: fixes for multisite replication of encrypted objects
This commit is contained in:
commit
1e1731e663
@ -4,5 +4,7 @@ overrides:
|
||||
conf:
|
||||
client:
|
||||
debug rgw: 20
|
||||
rgw crypt s3 kms encryption keys: testkey-1=YmluCmJvb3N0CmJvb3N0LWJ1aWxkCmNlcGguY29uZgo=
|
||||
rgw crypt require ssl: false
|
||||
rgw:
|
||||
compression type: random
|
||||
|
@ -203,6 +203,7 @@ protected:
|
||||
bool partial_content;
|
||||
bool range_parsed;
|
||||
bool skip_manifest;
|
||||
bool skip_decrypt{false};
|
||||
rgw_obj obj;
|
||||
utime_t gc_invalidate_time;
|
||||
bool is_slo;
|
||||
|
@ -7579,10 +7579,15 @@ int RGWRados::stat_remote_obj(RGWObjectCtx& obj_ctx,
|
||||
|
||||
obj_time_weight dest_mtime_weight;
|
||||
|
||||
constexpr bool prepend_meta = true;
|
||||
constexpr bool get_op = true;
|
||||
constexpr bool rgwx_stat = true;
|
||||
constexpr bool sync_manifest = true;
|
||||
constexpr bool skip_decrypt = true;
|
||||
int ret = conn->get_obj(user_id, info, src_obj, pmod, unmod_ptr,
|
||||
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
|
||||
true /* prepend_meta */, true /* GET */, true /* rgwx-stat */,
|
||||
true /* sync manifest */, &cb, &in_stream_req);
|
||||
prepend_meta, get_op, rgwx_stat,
|
||||
sync_manifest, skip_decrypt, &cb, &in_stream_req);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -7750,10 +7755,15 @@ int RGWRados::fetch_remote_obj(RGWObjectCtx& obj_ctx,
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool prepend_meta = true;
|
||||
static constexpr bool get_op = true;
|
||||
static constexpr bool rgwx_stat = false;
|
||||
static constexpr bool sync_manifest = true;
|
||||
static constexpr bool skip_decrypt = true;
|
||||
ret = conn->get_obj(user_id, info, src_obj, pmod, unmod_ptr,
|
||||
dest_mtime_weight.zone_short_id, dest_mtime_weight.pg_ver,
|
||||
true /* prepend_meta */, true /* GET */, false /* rgwx-stat */,
|
||||
true /* sync manifest */, &cb, &in_stream_req);
|
||||
prepend_meta, get_op, rgwx_stat,
|
||||
sync_manifest, skip_decrypt, &cb, &in_stream_req);
|
||||
if (ret < 0) {
|
||||
goto set_err_state;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ int RGWRESTConn::get_obj(const rgw_user& uid, req_info *info /* optional */, rgw
|
||||
const real_time *mod_ptr, const real_time *unmod_ptr,
|
||||
uint32_t mod_zone_id, uint64_t mod_pg_ver,
|
||||
bool prepend_metadata, bool get_op, bool rgwx_stat,
|
||||
bool sync_manifest, RGWGetDataCB *cb,
|
||||
bool sync_manifest, bool skip_decrypt, RGWGetDataCB *cb,
|
||||
RGWRESTStreamRWRequest **req)
|
||||
{
|
||||
string url;
|
||||
@ -175,6 +175,9 @@ int RGWRESTConn::get_obj(const rgw_user& uid, req_info *info /* optional */, rgw
|
||||
if (sync_manifest) {
|
||||
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "sync-manifest", ""));
|
||||
}
|
||||
if (skip_decrypt) {
|
||||
params.push_back(param_pair_t(RGW_SYS_PARAM_PREFIX "skip-decrypt", ""));
|
||||
}
|
||||
if (!obj.key.instance.empty()) {
|
||||
const string& instance = obj.key.instance;
|
||||
params.push_back(param_pair_t("versionId", instance));
|
||||
|
@ -94,7 +94,7 @@ public:
|
||||
const ceph::real_time *mod_ptr, const ceph::real_time *unmod_ptr,
|
||||
uint32_t mod_zone_id, uint64_t mod_pg_ver,
|
||||
bool prepend_metadata, bool get_op, bool rgwx_stat, bool sync_manifest,
|
||||
RGWGetDataCB *cb, RGWRESTStreamRWRequest **req);
|
||||
bool skip_decrypt, RGWGetDataCB *cb, RGWRESTStreamRWRequest **req);
|
||||
int complete_request(RGWRESTStreamRWRequest *req, string& etag, ceph::real_time *mtime, uint64_t *psize, map<string, string>& attrs);
|
||||
|
||||
int get_resource(const string& resource,
|
||||
|
@ -129,6 +129,12 @@ int RGWGetObj_ObjStore_S3::get_params()
|
||||
// all of the data from its parts. the parts will sync as separate objects
|
||||
skip_manifest = s->info.args.exists(RGW_SYS_PARAM_PREFIX "sync-manifest");
|
||||
|
||||
// multisite sync requests should fetch encrypted data, along with the
|
||||
// attributes needed to support decryption on the other zone
|
||||
if (s->system_request) {
|
||||
skip_decrypt = s->info.args.exists(RGW_SYS_PARAM_PREFIX "skip-decrypt");
|
||||
}
|
||||
|
||||
return RGWGetObj_ObjStore::get_params();
|
||||
}
|
||||
|
||||
@ -337,6 +343,10 @@ send_data:
|
||||
|
||||
int RGWGetObj_ObjStore_S3::get_decrypt_filter(std::unique_ptr<RGWGetDataCB> *filter, RGWGetDataCB* cb, bufferlist* manifest_bl)
|
||||
{
|
||||
if (skip_decrypt) { // bypass decryption for multisite sync requests
|
||||
return 0;
|
||||
}
|
||||
|
||||
int res = 0;
|
||||
std::unique_ptr<BlockCrypt> block_crypt;
|
||||
res = rgw_s3_prepare_decrypt(s, attrs, &block_crypt, crypt_http_responses);
|
||||
|
@ -930,3 +930,45 @@ def test_bucket_sync_disable_enable():
|
||||
|
||||
for bucket_name in buckets:
|
||||
zonegroup_bucket_checkpoint(zonegroup_conns, bucket_name)
|
||||
|
||||
def test_encrypted_object_sync():
|
||||
zonegroup = realm.master_zonegroup()
|
||||
zonegroup_conns = ZonegroupConns(zonegroup)
|
||||
|
||||
(zone1, zone2,) = zonegroup_conns.rw_zones
|
||||
|
||||
# create a bucket on the first zone
|
||||
bucket_name = gen_bucket_name()
|
||||
log.info('create bucket zone=%s name=%s', zone1.name, bucket_name)
|
||||
bucket = zone1.conn.create_bucket(bucket_name)
|
||||
|
||||
# upload an object with sse-c encryption
|
||||
sse_c_headers = {
|
||||
'x-amz-server-side-encryption-customer-algorithm': 'AES256',
|
||||
'x-amz-server-side-encryption-customer-key': 'pO3upElrwuEXSoFwCfnZPdSsmt/xWeFa0N9KgDijwVs=',
|
||||
'x-amz-server-side-encryption-customer-key-md5': 'DWygnHRtgiJ77HCm+1rvHw=='
|
||||
}
|
||||
key = bucket.new_key('testobj-sse-c')
|
||||
data = 'A'*512
|
||||
key.set_contents_from_string(data, headers=sse_c_headers)
|
||||
|
||||
# upload an object with sse-kms encryption
|
||||
sse_kms_headers = {
|
||||
'x-amz-server-side-encryption': 'aws:kms',
|
||||
# testkey-1 must be present in 'rgw crypt s3 kms encryption keys' (vstart.sh adds this)
|
||||
'x-amz-server-side-encryption-aws-kms-key-id': 'testkey-1',
|
||||
}
|
||||
key = bucket.new_key('testobj-sse-kms')
|
||||
key.set_contents_from_string(data, headers=sse_kms_headers)
|
||||
|
||||
# wait for the bucket metadata and data to sync
|
||||
zonegroup_meta_checkpoint(zonegroup)
|
||||
zone_bucket_checkpoint(zone2.zone, zone1.zone, bucket_name)
|
||||
|
||||
# read the encrypted objects from the second zone
|
||||
bucket2 = get_bucket(zone2, bucket_name)
|
||||
key = bucket2.get_key('testobj-sse-c', headers=sse_c_headers)
|
||||
eq(data, key.get_contents_as_string(headers=sse_c_headers))
|
||||
|
||||
key = bucket2.get_key('testobj-sse-kms')
|
||||
eq(data, key.get_contents_as_string())
|
||||
|
Loading…
Reference in New Issue
Block a user