@@ -36,6 +36,7 @@ const log = new DummyRequestLogger();
3636const splitter = constants . splitter ;
3737const canonicalID = 'accessKey1' ;
3838const authInfo = makeAuthInfo ( canonicalID ) ;
39+ const authInfoOtherAcc = makeAuthInfo ( 'accessKey2' ) ;
3940const namespace = 'default' ;
4041const bucketName = 'bucketname' ;
4142const lockedBucket = 'objectlockenabledbucket' ;
@@ -2559,9 +2560,14 @@ describe('complete mpu with bucket policy', () => {
25592560
25602561 beforeEach ( done => {
25612562 cleanup ( ) ;
2563+ sinon . spy ( metadataswitch , 'putObjectMD' ) ;
25622564 bucketPut ( authInfo , bucketPutRequest , log , done ) ;
25632565 } ) ;
25642566
2567+ afterEach ( ( ) => {
2568+ sinon . restore ( ) ;
2569+ } ) ;
2570+
25652571 it ( 'should complete with a deny on unrelated object as non root' , done => {
25662572 const bucketPutPolicyRequest = getPolicyRequest ( {
25672573 Version : '2012-10-17' ,
@@ -2628,4 +2634,94 @@ describe('complete mpu with bucket policy', () => {
26282634 done ( ) ;
26292635 } ) ;
26302636 } ) ;
2637+
2638+ it ( 'should set bucketOwnerId if requester is not destination bucket owner' , done => {
2639+ const partBody = Buffer . from ( 'I am a part\n' , 'utf8' ) ;
2640+ const bucketPutPolicyRequest = getPolicyRequest ( {
2641+ Version : '2012-10-17' ,
2642+ Statement : [
2643+ {
2644+ Effect : 'Allow' ,
2645+ Principal : { AWS : `arn:aws:iam::${ authInfoOtherAcc . shortid } :root` } ,
2646+ Action : [ 's3:*' ] ,
2647+ Resource : `arn:aws:s3:::${ bucketName } /*` ,
2648+ } ,
2649+ ] ,
2650+ } ) ;
2651+ async . waterfall ( [
2652+ next => bucketPutPolicy ( authInfo , bucketPutPolicyRequest , log , next ) ,
2653+ ( corsHeaders , next ) => initiateMultipartUpload ( authInfoOtherAcc ,
2654+ initiateReqFixed , log , next ) ,
2655+ ( result , corsHeaders , next ) => parseString ( result , next ) ,
2656+ ] ,
2657+ ( err , json ) => {
2658+ // Need to build request in here since do not have uploadId
2659+ // until here
2660+ assert . ifError ( err ) ;
2661+ const testUploadId =
2662+ json . InitiateMultipartUploadResult . UploadId [ 0 ] ;
2663+ const md5Hash = crypto . createHash ( 'md5' ) . update ( partBody ) ;
2664+ const calculatedHash = md5Hash . digest ( 'hex' ) ;
2665+ const partRequest = new DummyRequest ( Object . assign ( {
2666+ bucketName,
2667+ namespace,
2668+ objectKey,
2669+ headers : { host : `${ bucketName } .s3.amazonaws.com` } ,
2670+ url : `/${ objectKey } ?partNumber=1&uploadId=${ testUploadId } ` ,
2671+ query : {
2672+ partNumber : '1' ,
2673+ uploadId : testUploadId ,
2674+ } ,
2675+ // Note that the body of the post set in the request here does
2676+ // not really matter in this test.
2677+ // The put is not going through the route so the md5 is being
2678+ // calculated above and manually being set in the request below.
2679+ // What is being tested is that the calculatedHash being sent
2680+ // to the API for the part is stored and then used to
2681+ // calculate the final ETag upon completion
2682+ // of the multipart upload.
2683+ calculatedHash,
2684+ socket : {
2685+ remoteAddress : '1.1.1.1' ,
2686+ } ,
2687+ } , requestFix ) , partBody ) ;
2688+ objectPutPart ( authInfoOtherAcc , partRequest , undefined , log , err => {
2689+ assert . ifError ( err ) ;
2690+ const completeBody = '<CompleteMultipartUpload>' +
2691+ '<Part>' +
2692+ '<PartNumber>1</PartNumber>' +
2693+ `<ETag>"${ calculatedHash } "</ETag>` +
2694+ '</Part>' +
2695+ '</CompleteMultipartUpload>' ;
2696+ const completeRequest = new DummyRequest ( Object . assign ( {
2697+ bucketName,
2698+ namespace,
2699+ objectKey,
2700+ parsedHost : 's3.amazonaws.com' ,
2701+ url : `/${ objectKey } ?uploadId=${ testUploadId } ` ,
2702+ headers : { host : `${ bucketName } .s3.amazonaws.com` } ,
2703+ query : { uploadId : testUploadId } ,
2704+ post : completeBody ,
2705+ actionImplicitDenies : false ,
2706+ socket : {
2707+ remoteAddress : '1.1.1.1' ,
2708+ } ,
2709+ } , requestFix ) ) ;
2710+ completeMultipartUpload ( authInfoOtherAcc ,
2711+ completeRequest , log , err => {
2712+ assert . ifError ( err ) ;
2713+ sinon . assert . calledWith (
2714+ metadataswitch . putObjectMD . lastCall ,
2715+ bucketName ,
2716+ objectKey ,
2717+ sinon . match ( { bucketOwnerId : authInfo . canonicalId } ) ,
2718+ sinon . match . any ,
2719+ sinon . match . any ,
2720+ sinon . match . any
2721+ ) ;
2722+ done ( ) ;
2723+ } ) ;
2724+ } ) ;
2725+ } ) ;
2726+ } ) ;
26312727} ) ;
0 commit comments