@@ -3679,3 +3679,165 @@ def test_bucket_create_location_constraint():
36793679 Bucket = bucket_name ,
36803680 CreateBucketConfiguration = {'LocationConstraint' : zg .name })
36813681 assert e .response ['ResponseMetadata' ]['HTTPStatusCode' ] == 400
3682+
3683+ def allow_bucket_replication (function ):
3684+ def wrapper (* args , ** kwargs ):
3685+ zonegroup = realm .master_zonegroup ()
3686+ if len (zonegroup .zones ) < 2 :
3687+ raise SkipTest ("More than one zone needed in any one or multiple zone(s)." )
3688+
3689+ zones = "," .join ([z .name for z in zonegroup .zones ])
3690+ z = zonegroup .zones [0 ]
3691+ c = z .cluster
3692+
3693+ create_sync_policy_group (c , "sync-group" )
3694+ create_sync_group_flow_symmetrical (c , "sync-group" , "sync-flow" , zones )
3695+ create_sync_group_pipe (c , "sync-group" , "sync-pipe" , zones , zones )
3696+
3697+ zonegroup .period .update (z , commit = True )
3698+ realm_meta_checkpoint (realm )
3699+
3700+ try :
3701+ function (* args , ** kwargs )
3702+ finally :
3703+ remove_sync_group_pipe (c , "sync-group" , "sync-pipe" )
3704+ remove_sync_group_flow_symmetrical (c , "sync-group" , "sync-flow" )
3705+ remove_sync_policy_group (c , "sync-group" )
3706+
3707+ zonegroup .period .update (z , commit = True )
3708+ realm_meta_checkpoint (realm )
3709+
3710+ return wrapper
3711+
3712+ @allow_bucket_replication
3713+ def test_bucket_replication_normal ():
3714+ zonegroup = realm .master_zonegroup ()
3715+ zonegroup_conns = ZonegroupConns (zonegroup )
3716+
3717+ source = zonegroup_conns .non_account_rw_zones [0 ]
3718+ dest = zonegroup_conns .non_account_rw_zones [1 ]
3719+
3720+ source_bucket = source .create_bucket (gen_bucket_name ())
3721+ dest_bucket = dest .create_bucket (gen_bucket_name ())
3722+ zonegroup_meta_checkpoint (zonegroup )
3723+
3724+ # create replication configuration
3725+ response = source .s3_client .put_bucket_replication (
3726+ Bucket = source_bucket .name ,
3727+ ReplicationConfiguration = {
3728+ 'Role' : '' ,
3729+ 'Rules' : [{
3730+ 'ID' : 'rule1' ,
3731+ 'Status' : 'Enabled' ,
3732+ 'Destination' : {
3733+ 'Bucket' : f'arn:aws:s3:::{ dest_bucket .name } ' ,
3734+ }
3735+ }]
3736+ }
3737+ )
3738+ assert response ['ResponseMetadata' ]['HTTPStatusCode' ] == 200
3739+ zonegroup_meta_checkpoint (zonegroup )
3740+
3741+ # upload an object and wait for sync.
3742+ objname = 'dummy'
3743+ k = new_key (source , source_bucket , objname )
3744+ k .set_contents_from_string ('foo' )
3745+ zone_data_checkpoint (dest .zone , source .zone )
3746+
3747+ # check that object exists in destination bucket
3748+ k = get_key (dest , dest_bucket , objname )
3749+ assert_equal (k .get_contents_as_string ().decode ('utf-8' ), 'foo' )
3750+
3751+ @allow_bucket_replication
3752+ def test_bucket_replication_alt_user_forbidden ():
3753+ zonegroup = realm .master_zonegroup ()
3754+ zonegroup_conns = ZonegroupConns (zonegroup )
3755+
3756+ source = zonegroup_conns .non_account_rw_zones [0 ]
3757+ dest = zonegroup_conns .non_account_alt_rw_zones [1 ]
3758+
3759+ source_bucket = source .create_bucket (gen_bucket_name ())
3760+ dest_bucket = dest .create_bucket (gen_bucket_name ())
3761+ zonegroup_meta_checkpoint (zonegroup )
3762+
3763+ # create replication configuration
3764+ response = source .s3_client .put_bucket_replication (
3765+ Bucket = source_bucket .name ,
3766+ ReplicationConfiguration = {
3767+ 'Role' : '' ,
3768+ 'Rules' : [{
3769+ 'ID' : 'rule1' ,
3770+ 'Status' : 'Enabled' ,
3771+ 'Destination' : {
3772+ 'Bucket' : f'arn:aws:s3:::{ dest_bucket .name } ' ,
3773+ }
3774+ }]
3775+ }
3776+ )
3777+ assert response ['ResponseMetadata' ]['HTTPStatusCode' ] == 200
3778+ zonegroup_meta_checkpoint (zonegroup )
3779+
3780+ # upload an object and wait for sync.
3781+ objname = 'dummy'
3782+ k = new_key (source , source_bucket , objname )
3783+ k .set_contents_from_string ('foo' )
3784+ zone_data_checkpoint (dest .zone , source .zone )
3785+
3786+ # check that object does not exist in destination bucket
3787+ e = assert_raises (ClientError , dest .s3_client .get_object , Bucket = dest_bucket .name , Key = objname )
3788+ assert e .response ['Error' ]['Code' ] == 'NoSuchKey'
3789+
3790+ @allow_bucket_replication
3791+ def test_bucket_replication_alt_user ():
3792+ zonegroup = realm .master_zonegroup ()
3793+ zonegroup_conns = ZonegroupConns (zonegroup )
3794+
3795+ source = zonegroup_conns .non_account_rw_zones [0 ]
3796+ dest = zonegroup_conns .non_account_alt_rw_zones [1 ]
3797+
3798+ source_bucket = source .create_bucket (gen_bucket_name ())
3799+ dest_bucket = dest .create_bucket (gen_bucket_name ())
3800+ zonegroup_meta_checkpoint (zonegroup )
3801+
3802+ # create replication configuration
3803+ response = source .s3_client .put_bucket_replication (
3804+ Bucket = source_bucket .name ,
3805+ ReplicationConfiguration = {
3806+ 'Role' : '' ,
3807+ 'Rules' : [{
3808+ 'ID' : 'rule1' ,
3809+ 'Status' : 'Enabled' ,
3810+ 'Destination' : {
3811+ 'Bucket' : f'arn:aws:s3:::{ dest_bucket .name } ' ,
3812+ 'AccessControlTranslation' : {
3813+ 'Owner' : non_account_alt_user .id ,
3814+ },
3815+ }
3816+ }]
3817+ }
3818+ )
3819+ assert response ['ResponseMetadata' ]['HTTPStatusCode' ] == 200
3820+ # give access to user to write to alt user's bucket
3821+ dest .s3_client .put_bucket_policy (
3822+ Bucket = dest_bucket .name ,
3823+ Policy = json .dumps ({
3824+ 'Version' : '2012-10-17' ,
3825+ 'Statement' : [{
3826+ 'Effect' : 'Allow' ,
3827+ 'Principal' : {'AWS' : [f"arn:aws:iam:::user/{ user .id } " ]},
3828+ 'Action' : 's3:PutObject' ,
3829+ 'Resource' : f'arn:aws:s3:::{ dest_bucket .name } /*' ,
3830+ }]
3831+ })
3832+ )
3833+ zonegroup_meta_checkpoint (zonegroup )
3834+
3835+ # upload an object and wait for sync.
3836+ objname = 'dummy'
3837+ k = new_key (source , source_bucket , objname )
3838+ k .set_contents_from_string ('foo' )
3839+ zone_data_checkpoint (dest .zone , source .zone )
3840+
3841+ # check that object exists in destination bucket
3842+ k = get_key (dest , dest_bucket , objname )
3843+ assert_equal (k .get_contents_as_string ().decode ('utf-8' ), 'foo' )
0 commit comments