@@ -38,6 +38,7 @@ const log = new DummyRequestLogger();
3838const splitter = constants . splitter ;
3939const canonicalID = 'accessKey1' ;
4040const authInfo = makeAuthInfo ( canonicalID ) ;
41+ const authInfoOtherAcc = makeAuthInfo ( 'accessKey2' ) ;
4142const namespace = 'default' ;
4243const bucketName = 'bucketname' ;
4344const lockedBucket = 'objectlockenabledbucket' ;
@@ -2661,9 +2662,14 @@ describe('complete mpu with bucket policy', () => {
26612662
26622663 beforeEach ( done => {
26632664 cleanup ( ) ;
2665+ sinon . spy ( metadataswitch , 'putObjectMD' ) ;
26642666 bucketPut ( authInfo , bucketPutRequest , log , done ) ;
26652667 } ) ;
26662668
2669+ afterEach ( ( ) => {
2670+ sinon . restore ( ) ;
2671+ } ) ;
2672+
26672673 it ( 'should complete with a deny on unrelated object as non root' , done => {
26682674 const bucketPutPolicyRequest = getPolicyRequest ( {
26692675 Version : '2012-10-17' ,
@@ -2730,6 +2736,96 @@ describe('complete mpu with bucket policy', () => {
27302736 done ( ) ;
27312737 } ) ;
27322738 } ) ;
2739+
2740+ it ( 'should set bucketOwnerId if requester is not destination bucket owner' , done => {
2741+ const partBody = Buffer . from ( 'I am a part\n' , 'utf8' ) ;
2742+ const bucketPutPolicyRequest = getPolicyRequest ( {
2743+ Version : '2012-10-17' ,
2744+ Statement : [
2745+ {
2746+ Effect : 'Allow' ,
2747+ Principal : { AWS : `arn:aws:iam::${ authInfoOtherAcc . shortid } :root` } ,
2748+ Action : [ 's3:*' ] ,
2749+ Resource : `arn:aws:s3:::${ bucketName } /*` ,
2750+ } ,
2751+ ] ,
2752+ } ) ;
2753+ async . waterfall ( [
2754+ next => bucketPutPolicy ( authInfo , bucketPutPolicyRequest , log , next ) ,
2755+ ( corsHeaders , next ) => initiateMultipartUpload ( authInfoOtherAcc ,
2756+ initiateRequest , log , next ) ,
2757+ ( result , corsHeaders , next ) => parseString ( result , next ) ,
2758+ ] ,
2759+ ( err , json ) => {
2760+ // Need to build request in here since do not have uploadId
2761+ // until here
2762+ assert . ifError ( err ) ;
2763+ const testUploadId =
2764+ json . InitiateMultipartUploadResult . UploadId [ 0 ] ;
2765+ const md5Hash = crypto . createHash ( 'md5' ) . update ( partBody ) ;
2766+ const calculatedHash = md5Hash . digest ( 'hex' ) ;
2767+ const partRequest = new DummyRequest ( {
2768+ bucketName,
2769+ namespace,
2770+ objectKey,
2771+ headers : { host : `${ bucketName } .s3.amazonaws.com` } ,
2772+ url : `/${ objectKey } ?partNumber=1&uploadId=${ testUploadId } ` ,
2773+ query : {
2774+ partNumber : '1' ,
2775+ uploadId : testUploadId ,
2776+ } ,
2777+ // Note that the body of the post set in the request here does
2778+ // not really matter in this test.
2779+ // The put is not going through the route so the md5 is being
2780+ // calculated above and manually being set in the request below.
2781+ // What is being tested is that the calculatedHash being sent
2782+ // to the API for the part is stored and then used to
2783+ // calculate the final ETag upon completion
2784+ // of the multipart upload.
2785+ calculatedHash,
2786+ socket : {
2787+ remoteAddress : '1.1.1.1' ,
2788+ } ,
2789+ } , partBody ) ;
2790+ objectPutPart ( authInfoOtherAcc , partRequest , undefined , log , err => {
2791+ assert . ifError ( err ) ;
2792+ const completeBody = '<CompleteMultipartUpload>' +
2793+ '<Part>' +
2794+ '<PartNumber>1</PartNumber>' +
2795+ `<ETag>"${ calculatedHash } "</ETag>` +
2796+ '</Part>' +
2797+ '</CompleteMultipartUpload>' ;
2798+ const completeRequest = {
2799+ bucketName,
2800+ namespace,
2801+ objectKey,
2802+ parsedHost : 's3.amazonaws.com' ,
2803+ url : `/${ objectKey } ?uploadId=${ testUploadId } ` ,
2804+ headers : { host : `${ bucketName } .s3.amazonaws.com` } ,
2805+ query : { uploadId : testUploadId } ,
2806+ post : completeBody ,
2807+ actionImplicitDenies : false ,
2808+ socket : {
2809+ remoteAddress : '1.1.1.1' ,
2810+ } ,
2811+ } ;
2812+ completeMultipartUpload ( authInfoOtherAcc ,
2813+ completeRequest , log , err => {
2814+ assert . ifError ( err ) ;
2815+ sinon . assert . calledWith (
2816+ metadataswitch . putObjectMD . lastCall ,
2817+ bucketName ,
2818+ objectKey ,
2819+ sinon . match ( { bucketOwnerId : authInfo . canonicalId } ) ,
2820+ sinon . match . any ,
2821+ sinon . match . any ,
2822+ sinon . match . any
2823+ ) ;
2824+ done ( ) ;
2825+ } ) ;
2826+ } ) ;
2827+ } ) ;
2828+ } ) ;
27332829} ) ;
27342830
27352831describe ( 'multipart upload in ingestion bucket' , ( ) => {
0 commit comments