Merge pull request #16612 from cbodley/wip-20668

rgw: fixes for multisite replication of encrypted objects
This commit is contained in:
Matt Benjamin 2017-08-23 15:57:02 -04:00 committed by GitHub
commit 1e1731e663
7 changed files with 74 additions and 6 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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));

View File

@ -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,

View File

@ -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);

View File

@ -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())