@@ -505,59 +505,82 @@ describe('ensure MPU use good SSE', () => {
505505 ) ;
506506 } ) ;
507507} ) ;
508-
509508describe ( 'KMS error' , ( ) => {
510- const sseConfig = { algo : 'aws:kms' , masterKeyId : true }
509+ const sseConfig = { algo : 'aws:kms' , masterKeyId : true } ;
511510 const Bucket = 'bkt-kms-err' ;
512511 const Key = 'obj' ;
513512 const body = 'content' ;
514513
515- let masterKeyId , masterKeyArn ;
516- let anotherKeyInfo ;
514+ let mpuEncrypted ;
515+ let mpuPlaintext ;
516+
517+ let masterKeyId ;
518+ let masterKeyArn ;
517519
518- let expectedErr , expectedMsg ;
520+ let expected ;
519521
520522 const expectedKMIP = {
521- code : / K M S \ .N o t F o u n d E x c e p t i o n / ,
523+ code : ' KMS.NotFoundException' ,
522524 msg : ( action , keyId ) => new RegExp ( `^KMS \\(KMIP\\) error for ${ action } on ${ keyId } \\..*` ) ,
523525 } ;
524- // localkms container returns a different error message when the key is pending deletion
525- // as we decrypt without passing the keyId, so we need to handle it separately
526- const localKms = 'The ciphertext refers to a customer master key that does not exist, ' +
527- 'does not exist in this region, or you are not allowed to access\\.' ;
528526 const expectedAWS = {
529- code : / K M S \. K M S I n v a l i d S t a t e E x c e p t i o n | K M S \. A c c e s s D e n i e d E x c e p t i o n / ,
530- msg : ( _ , keyId ) => new RegExp ( `${ keyId } is pending deletion\\.|${ localKms } ` ) ,
527+ code : 'KMS.KMSInvalidStateException' ,
528+ msg : ( _ , keyId ) => new RegExp ( `${ keyId } is pending deletion\\.` ) ,
529+ } ;
530+ /**
531+ * localkms container returns a different error message when the key is pending deletion
532+ * as we decrypt without passing the keyId, so we need to handle it separately
533+ */
534+ const expectedLocalKms = {
535+ code : 'KMS.AccessDeniedException' ,
536+ msg : ( ) => new RegExp (
537+ 'The ciphertext refers to a customer master key that does not exist, ' +
538+ 'does not exist in this region, or you are not allowed to access\\.'
539+ ) ,
531540 } ;
532-
533541 if ( helpers . config . backends . kms === 'kmip' ) {
534- ( { code : expectedErr , msg : expectedMsg } = expectedKMIP ) ;
542+ expected = expectedKMIP ;
535543 } else if ( helpers . config . backends . kms === 'aws' ) {
536- ( { code : expectedErr , msg : expectedMsg } = expectedAWS ) ;
544+ expected = expectedAWS ;
537545 } else {
538546 throw new Error ( `Unsupported KMS backend: ${ helpers . config . backends . kms } ` ) ;
539547 }
540548
541549 function assertKmsError ( action , keyId ) {
542550 return err => {
543- assert . match ( err . name , expectedErr ) ;
544- assert . match ( err . message , expectedMsg ( action , keyId ) ) ;
551+ if ( helpers . config . backends . kms === 'aws' && action === 'Decrypt' ) {
552+ assert . strictEqual ( err . name , expectedLocalKms . code ) ;
553+ assert . match ( err . message , expectedLocalKms . msg ( action , keyId ) ) ;
554+ return true ;
555+ }
556+ assert . strictEqual ( err . name , expected . code ) ;
557+ assert . match ( err . message , expected . msg ( action , keyId ) ) ;
545558 return true ;
546559 } ;
547560 }
548561
549562 before ( async ( ) => {
550563 void await helpers . s3 . createBucket ( { Bucket } ) . promise ( ) ;
564+
551565 await helpers . s3 . putObject ( {
552566 ...helpers . putObjParams ( Bucket , 'plaintext' , { } , null ) ,
553567 Body : body ,
554568 } ) . promise ( ) ;
555569
570+ mpuPlaintext = await helpers . s3 . createMultipartUpload (
571+ helpers . putObjParams ( Bucket , 'mpuPlaintext' , { } , null ) ) . promise ( ) ;
572+
556573 ( { masterKeyId, masterKeyArn } = await helpers . createKmsKey ( log ) ) ;
574+
557575 await helpers . putEncryptedObject ( Bucket , Key , sseConfig , masterKeyArn , body ) ;
558576 // ensure we can decrypt and read the object
559577 const obj = await helpers . s3 . getObject ( { Bucket, Key } ) . promise ( ) ;
560578 assert . strictEqual ( obj . Body . toString ( ) , body ) ;
579+
580+ mpuEncrypted = await helpers . s3 . createMultipartUpload (
581+ helpers . putObjParams ( Bucket , 'mpuEncrypted' , sseConfig , masterKeyArn ) ) . promise ( ) ;
582+
583+ // make key unavailable
561584 void await helpers . destroyKmsKey ( masterKeyArn , log ) ;
562585 } ) ;
563586
@@ -571,96 +594,74 @@ describe('KMS error', () => {
571594 }
572595 } ) ;
573596
574- afterEach ( async ( ) => {
575- if ( anotherKeyInfo ) {
576- try {
577- void await helpers . destroyKmsKey ( anotherKeyInfo . masterKeyArn , log ) ;
578- } catch ( e ) { void e ; }
579- anotherKeyInfo = null ;
580- }
581- } ) ;
582-
583- it ( 'putObject should fail with kms error' , async ( ) => {
584- await assert . rejects ( helpers . putEncryptedObject ( Bucket , 'fail' , sseConfig , masterKeyArn , body ) ,
585- assertKmsError ( 'Encrypt' , masterKeyId ) ) ;
586- } ) ;
587-
588- it ( 'getObject should fail with kms error' , async ( ) => {
589- await assert . rejects ( helpers . s3 . getObject ( { Bucket, Key } ) . promise ( ) ,
590- assertKmsError ( 'Decrypt' , masterKeyId ) ) ;
591- } ) ;
592-
593- it ( 'copyObject should fail with kms error when getting from source' , async ( ) => {
594- await assert . rejects ( helpers . s3 . copyObject (
595- { Bucket, Key : 'copy' , CopySource : `${ Bucket } /${ Key } ` } ) . promise ( ) ,
596- assertKmsError ( 'Decrypt' , masterKeyId )
597- ) ;
598- } ) ;
599-
600- it ( 'copyObject should fail with kms error when putting to destination' , async ( ) => {
601- await assert . rejects ( helpers . s3 . copyObject (
602- {
597+ const testCases = [
598+ {
599+ action : 'putObject' , kmsAction : 'Encrypt' ,
600+ fct : async ( { masterKeyArn } ) =>
601+ helpers . putEncryptedObject ( Bucket , 'fail' , sseConfig , masterKeyArn , body ) ,
602+ } ,
603+ {
604+ action : 'getObject' , kmsAction : 'Decrypt' ,
605+ fct : async ( ) => helpers . s3 . getObject ( { Bucket, Key } ) . promise ( ) ,
606+ } ,
607+ {
608+ action : 'copyObject' , detail : ' when getting from source' , kmsAction : 'Decrypt' ,
609+ fct : async ( ) =>
610+ helpers . s3 . copyObject ( { Bucket, Key : 'copy' , CopySource : `${ Bucket } /${ Key } ` } ) . promise ( ) ,
611+ } ,
612+ {
613+ action : 'copyObject' , detail : ' when putting to destination' , kmsAction : 'Encrypt' ,
614+ fct : async ( { masterKeyArn } ) => helpers . s3 . copyObject ( {
603615 Bucket,
604616 Key : 'copyencrypted' ,
605617 CopySource : `${ Bucket } /plaintext` ,
606618 ServerSideEncryption : 'aws:kms' ,
607619 SSEKMSKeyId : masterKeyArn ,
608- }
609- ) . promise ( ) ,
610- assertKmsError ( 'Encrypt' , masterKeyId ) ) ;
611- } ) ;
612-
613- it ( 'createMPU should fail with kms error' , async ( ) => {
614- const mpuKey = 'mpuKeyEncryptedFail' ;
615- await assert . rejects ( helpers . s3 . createMultipartUpload (
616- helpers . putObjParams ( Bucket , mpuKey , sseConfig , masterKeyArn ) ) . promise ( ) ,
617- assertKmsError ( 'Encrypt' , masterKeyId ) ) ;
618- } ) ;
619-
620- it ( 'mpu uploadPartCopy should fail with kms error when getting from source' , async ( ) => {
621- const mpuKey = 'mpuKey' ;
622- const mpu = await helpers . s3 . createMultipartUpload (
623- helpers . putObjParams ( Bucket , mpuKey , { } , null ) ) . promise ( ) ;
624- await assert . rejects ( helpers . s3 . uploadPartCopy (
625- {
626- UploadId : mpu . UploadId ,
620+ } ) . promise ( ) ,
621+ } ,
622+ {
623+ action : 'createMPU' , kmsAction : 'Encrypt' ,
624+ fct : async ( { masterKeyArn } ) => helpers . s3 . createMultipartUpload (
625+ helpers . putObjParams ( Bucket , 'mpuKeyEncryptedFail' , sseConfig , masterKeyArn ) ) . promise ( ) ,
626+ } ,
627+ {
628+ action : 'mpu uploadPartCopy' , detail : ' when getting from source' , kmsAction : 'Decrypt' ,
629+ fct : async ( { mpuPlaintext } ) => helpers . s3 . uploadPartCopy ( {
630+ UploadId : mpuPlaintext . UploadId ,
627631 Bucket,
628- Key : mpuKey ,
632+ Key : 'mpuPlaintext' ,
629633 PartNumber : 1 ,
630634 CopySource : `${ Bucket } /${ Key } ` ,
631- }
632- ) . promise ( ) ,
633- assertKmsError ( 'Decrypt' , masterKeyId ) ) ;
634- } ) ;
635-
636- it ( 'mpu uploadPart & copy should fail with kms error when putting to destination' , async ( ) => {
637- const mpuKey = 'mpuKeyEncrypted' ;
638- anotherKeyInfo = await helpers . createKmsKey ( log ) ;
639-
640- const mpu = await helpers . s3 . createMultipartUpload (
641- helpers . putObjParams ( Bucket , mpuKey , sseConfig , anotherKeyInfo . masterKeyArn ) ) . promise ( ) ;
642-
643- void await helpers . destroyKmsKey ( anotherKeyInfo . masterKeyArn , log ) ;
644- await assert . rejects ( helpers . s3 . uploadPart (
645- {
646- UploadId : mpu . UploadId ,
635+ } ) . promise ( ) ,
636+ } ,
637+ {
638+ action : 'mpu uploadPart' , detail : ' when putting to destination' , kmsAction : 'Encrypt' ,
639+ fct : async ( { mpuEncrypted } ) => helpers . s3 . uploadPart ( {
640+ UploadId : mpuEncrypted . UploadId ,
647641 Bucket,
648- Key : mpuKey ,
642+ Key : 'mpuEncrypted' ,
649643 PartNumber : 1 ,
650644 Body : body ,
651- }
652- ) . promise ( ) ,
653- assertKmsError ( 'Encrypt' , anotherKeyInfo . masterKeyId ) ) ;
654-
655- await assert . rejects ( helpers . s3 . uploadPartCopy (
656- {
657- UploadId : mpu . UploadId ,
645+ } ) . promise ( ) ,
646+ } ,
647+ {
648+ action : 'mpu uploadPartCopy' , detail : ' when putting to destination' , kmsAction : 'Encrypt' ,
649+ fct : async ( { mpuEncrypted } ) => helpers . s3 . uploadPartCopy ( {
650+ UploadId : mpuEncrypted . UploadId ,
658651 Bucket,
659- Key : mpuKey ,
652+ Key : 'mpuEncrypted' ,
660653 PartNumber : 1 ,
661654 CopySource : `${ Bucket } /plaintext` ,
662- }
663- ) . promise ( ) ,
664- assertKmsError ( 'Encrypt' , anotherKeyInfo . masterKeyId ) ) ;
655+ } ) . promise ( ) ,
656+ } ,
657+ ] ;
658+
659+ testCases . forEach ( ( { action, kmsAction, fct, detail } ) => {
660+ it ( `${ action } should fail with kms error${ detail || '' } ` , async ( ) => {
661+ await assert . rejects (
662+ fct ( { masterKeyArn, mpuEncrypted, mpuPlaintext } ) ,
663+ assertKmsError ( kmsAction , masterKeyId ) ,
664+ ) ;
665+ } ) ;
665666 } ) ;
666667} ) ;
0 commit comments