@@ -24,6 +24,8 @@ const { getObjectSSEConfiguration } = require('./apiUtils/bucket/bucketEncryptio
2424const { setExpirationHeaders } = require ( './apiUtils/object/expirationHeaders' ) ;
2525const { setSSEHeaders } = require ( './apiUtils/object/sseHeaders' ) ;
2626const { updateEncryption } = require ( './apiUtils/bucket/updateEncryption' ) ;
27+ const { getChecksumDataFromMPUHeaders, arsenalErrorFromChecksumError } =
28+ require ( './apiUtils/integrity/validateChecksums' ) ;
2729const { config } = require ( '../Config' ) ;
2830const kms = require ( '../kms/wrapper' ) ;
2931
@@ -87,6 +89,13 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
8789 `value ${ websiteRedirectHeader } ` , { error : err } ) ;
8890 return callback ( err ) ;
8991 }
92+ const checksumConfig = getChecksumDataFromMPUHeaders ( request . headers ) ;
93+ if ( checksumConfig . error ) {
94+ const checksumErr = arsenalErrorFromChecksumError ( checksumConfig ) ;
95+ log . debug ( 'checksum header validation failed' , { error : checksumErr , method : 'initiateMultipartUpload' } ) ;
96+ monitoring . promMetrics ( 'PUT' , bucketName , checksumErr . code , 'initiateMultipartUpload' ) ;
97+ return callback ( checksumErr ) ;
98+ }
9099 const metaHeaders = getMetaHeaders ( request . headers ) ;
91100 if ( metaHeaders instanceof Error ) {
92101 log . debug ( 'user metadata validation failed' , {
@@ -145,13 +154,15 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
145154 initiatorDisplayName,
146155 splitter : constants . splitter ,
147156 } ;
157+ metadataStoreParams . checksumAlgorithm = checksumConfig . algorithm ;
158+ metadataStoreParams . checksumType = checksumConfig . type ;
159+ metadataStoreParams . checksumIsDefault = checksumConfig . isDefault ;
148160 const tagging = request . headers [ 'x-amz-tagging' ] ;
149161 if ( tagging ) {
150162 metadataStoreParams . tagging = tagging ;
151163 }
152164
153- function _getMPUBucket ( destinationBucket , log , corsHeaders ,
154- uploadId , cipherBundle , locConstraint , callback ) {
165+ function _getMPUBucket ( destinationBucket , log , corsHeaders , uploadId , cipherBundle , locConstraint , callback ) {
155166 const xmlParams = {
156167 bucketName,
157168 objectKey,
@@ -205,6 +216,14 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
205216 mpuMD [ 'x-amz-server-side-encryption' ] ,
206217 mpuMD [ 'x-amz-server-side-encryption-aws-kms-key-id' ] ) ;
207218
219+ // Only respond the headers if the user sent them
220+ if ( ! checksumConfig . isDefault ) {
221+ // eslint-disable-next-line no-param-reassign
222+ corsHeaders [ 'x-amz-checksum-algorithm' ] = checksumConfig . algorithm . toUpperCase ( ) ;
223+ // eslint-disable-next-line no-param-reassign
224+ corsHeaders [ 'x-amz-checksum-type' ] = checksumConfig . type ;
225+ }
226+
208227 monitoring . promMetrics ( 'PUT' , bucketName , '200' ,
209228 'initiateMultipartUpload' ) ;
210229 return callback ( null , xml , corsHeaders ) ;
@@ -279,47 +298,48 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
279298 }
280299
281300 return data . initiateMPU ( mpuInfo , websiteRedirectHeader , log ,
282- ( err , dataBackendResObj , isVersionedObj ) => {
283- // will return as true and a custom error if external backend does
284- // not support versioned objects
285- if ( isVersionedObj ) {
286- monitoring . promMetrics ( 'PUT' , bucketName , 501 ,
287- 'initiateMultipartUpload' ) ;
288- return callback ( err ) ;
289- }
290- if ( err ) {
291- monitoring . promMetrics ( 'PUT' , bucketName , err . code ,
292- 'initiateMultipartUpload' ) ;
293- return callback ( err ) ;
294- }
295- // if mpu not handled externally, dataBackendResObj will be null
296- if ( dataBackendResObj ) {
297- uploadId = dataBackendResObj . UploadId ;
298- } else {
299- // Generate uniqueID without dashes so routing not messed up
300- uploadId = uuidv4 ( ) . replace ( / - / g, '' ) ;
301- }
302- return _getMPUBucket ( destinationBucket , log , corsHeaders ,
303- uploadId , cipherBundle , locConstraint , callback ) ;
304- } ) ;
301+ ( err , dataBackendResObj , isVersionedObj ) => {
302+ // will return as true and a custom error if external backend does
303+ // not support versioned objects
304+ if ( isVersionedObj ) {
305+ monitoring . promMetrics ( 'PUT' , bucketName , 501 ,
306+ 'initiateMultipartUpload' ) ;
307+ return callback ( err ) ;
308+ }
309+ if ( err ) {
310+ monitoring . promMetrics ( 'PUT' , bucketName , err . code ,
311+ 'initiateMultipartUpload' ) ;
312+ return callback ( err ) ;
313+ }
314+ // if mpu not handled externally, dataBackendResObj will be null
315+ if ( dataBackendResObj ) {
316+ uploadId = dataBackendResObj . UploadId ;
317+ } else {
318+ // Generate uniqueID without dashes so routing not messed up
319+ uploadId = uuidv4 ( ) . replace ( / - / g, '' ) ;
320+ }
321+ return _getMPUBucket ( destinationBucket , log , corsHeaders ,
322+ uploadId , cipherBundle , locConstraint , callback ) ;
323+ } ) ;
305324 }
306325
307326 async . waterfall ( [
308327 next => standardMetadataValidateBucketAndObj ( metadataValParams , request . actionImplicitDenies , log ,
309328 ( error , destinationBucket , destObjMD ) =>
310329 updateEncryption ( error , destinationBucket , destObjMD , objectKey , log , { skipObject : true } ,
311- ( error , destinationBucket ) => {
312- const corsHeaders = collectCorsHeaders ( request . headers . origin , request . method , destinationBucket ) ;
313- if ( error ) {
314- log . debug ( 'error processing request' , {
315- error,
316- method : 'metadataValidateBucketAndObj' ,
317- } ) ;
318- monitoring . promMetrics ( 'PUT' , bucketName , error . code , 'initiateMultipartUpload' ) ;
319- return next ( error , corsHeaders ) ;
320- }
321- return next ( null , corsHeaders , destinationBucket ) ;
322- } ) ) ,
330+ ( error , destinationBucket ) => {
331+ const corsHeaders = collectCorsHeaders (
332+ request . headers . origin , request . method , destinationBucket ) ;
333+ if ( error ) {
334+ log . debug ( 'error processing request' , {
335+ error,
336+ method : 'metadataValidateBucketAndObj' ,
337+ } ) ;
338+ monitoring . promMetrics ( 'PUT' , bucketName , error . code , 'initiateMultipartUpload' ) ;
339+ return next ( error , corsHeaders ) ;
340+ }
341+ return next ( null , corsHeaders , destinationBucket ) ;
342+ } ) ) ,
323343 ( corsHeaders , destinationBucket , next ) => {
324344 if ( destinationBucket . hasDeletedFlag ( ) && accountCanonicalID !== destinationBucket . getOwner ( ) ) {
325345 log . trace ( 'deleted flag on bucket and request from non-owner account' ) ;
@@ -329,25 +349,25 @@ function initiateMultipartUpload(authInfo, request, log, callback) {
329349 if ( destinationBucket . hasTransientFlag ( ) || destinationBucket . hasDeletedFlag ( ) ) {
330350 log . trace ( 'transient or deleted flag so cleaning up bucket' ) ;
331351 return cleanUpBucket (
332- destinationBucket ,
333- accountCanonicalID ,
334- log ,
335- error => {
336- if ( error ) {
337- log . debug ( 'error cleaning up bucket with flag' ,
338- {
339- error,
340- transientFlag : destinationBucket . hasTransientFlag ( ) ,
341- deletedFlag : destinationBucket . hasDeletedFlag ( ) ,
342- } ) ;
343- // To avoid confusing user with error
344- // from cleaning up
345- // bucket return InternalError
346- monitoring . promMetrics ( 'PUT' , bucketName , 500 , 'initiateMultipartUpload' ) ;
347- return next ( errors . InternalError , corsHeaders ) ;
348- }
349- return next ( null , corsHeaders , destinationBucket ) ;
350- } ) ;
352+ destinationBucket ,
353+ accountCanonicalID ,
354+ log ,
355+ error => {
356+ if ( error ) {
357+ log . debug ( 'error cleaning up bucket with flag' ,
358+ {
359+ error,
360+ transientFlag : destinationBucket . hasTransientFlag ( ) ,
361+ deletedFlag : destinationBucket . hasDeletedFlag ( ) ,
362+ } ) ;
363+ // To avoid confusing user with error
364+ // from cleaning up
365+ // bucket return InternalError
366+ monitoring . promMetrics ( 'PUT' , bucketName , 500 , 'initiateMultipartUpload' ) ;
367+ return next ( errors . InternalError , corsHeaders ) ;
368+ }
369+ return next ( null , corsHeaders , destinationBucket ) ;
370+ } ) ;
351371 }
352372 return next ( null , corsHeaders , destinationBucket ) ;
353373 } ,
0 commit comments