@@ -5,7 +5,7 @@ const { promisify } = require('util');
55const metadataUtils = require ( '../../../lib/metadata/metadataUtils' ) ;
66const storeObject = require ( '../../../lib/api/apiUtils/object/storeObject' ) ;
77const metadata = require ( '../../../lib/metadata/wrapper' ) ;
8- const { routeBackbeat, backbeatRoutes } = require ( '../../../lib/routes/routeBackbeat' ) ;
8+ const { routeBackbeat } = require ( '../../../lib/routes/routeBackbeat' ) ;
99const { DummyRequestLogger, versioningTestUtils, makeAuthInfo } = require ( '../helpers' ) ;
1010const dataWrapper = require ( '../../../lib/data/wrapper' ) ;
1111const DummyRequest = require ( '../DummyRequest' ) ;
@@ -14,8 +14,10 @@ const AuthInfo = auth.AuthInfo;
1414const { config } = require ( '../../../lib/Config' ) ;
1515const quotaUtils = require ( '../../../lib/api/apiUtils/quotas/quotaUtils' ) ;
1616const { bucketPut } = require ( '../../../lib/api/bucketPut' ) ;
17- const objectPut = require ( '../../../lib/api/objectPut ' ) ;
17+ const bucketDelete = require ( '../../../lib/api/bucketDelete ' ) ;
1818const bucketPutVersioning = require ( '../../../lib/api/bucketPutVersioning' ) ;
19+ const objectPut = require ( '../../../lib/api/objectPut' ) ;
20+ const { objectDelete } = require ( '../../../lib/api/objectDelete' ) ;
1921
2022const log = new DummyRequestLogger ( ) ;
2123
@@ -702,12 +704,12 @@ describe('routeBackbeat', () => {
702704} ) ;
703705
704706describe ( 'routeBackbeat authorization' , ( ) => {
707+ let endPromise ;
708+ let resolveEnd ;
705709 const bucketName = 'bucketname' ;
706- const canonicalID = 'accessKey1' ;
707- const authInfo = makeAuthInfo ( canonicalID ) ;
710+ const authInfo = makeAuthInfo ( 'cannonicalID' , ) ;
708711 const namespace = 'default' ;
709712 const objectName = 'objectName' ;
710- const postBody = Buffer . from ( 'I am a body' , 'utf8' ) ;
711713
712714 const testBucket = {
713715 bucketName,
@@ -729,49 +731,14 @@ describe('routeBackbeat authorization', () => {
729731 } ,
730732 parsedContentLength : 12 ,
731733 url : `/${ bucketName } /${ objectName } ` ,
732- } , postBody ) ;
734+ } , Buffer . from ( 'I am a body' , 'utf8' ) ) ;
733735
734736 let request ;
735737 let response ;
736738
737739 beforeEach ( ( ) => {
738- sinon . stub ( backbeatRoutes , 'PUT' ) . returns ( {
739- data : sinon . stub ( ) ,
740- metadata : sinon . stub ( ) ,
741- multiplebackenddata : {
742- putobject : sinon . stub ( ) ,
743- putpart : sinon . stub ( ) ,
744- } ,
745- } ) ;
746-
747- sinon . stub ( backbeatRoutes , 'POST' ) . returns ( {
748- multiplebackenddata : {
749- initiatempu : sinon . stub ( ) ,
750- completempu : sinon . stub ( ) ,
751- puttagging : sinon . stub ( ) ,
752- } ,
753- batchdelete : sinon . stub ( ) ,
754- index : {
755- add : sinon . stub ( ) ,
756- delete : sinon . stub ( ) ,
757- } ,
758- } ) ;
759-
760- sinon . stub ( backbeatRoutes , 'DELETE' ) . returns ( {
761- expiration : sinon . stub ( ) ,
762- multiplebackenddata : {
763- deleteobject : sinon . stub ( ) ,
764- deleteobjecttagging : sinon . stub ( ) ,
765- abortmpu : sinon . stub ( ) ,
766- } ,
767- } ) ;
768-
769- sinon . stub ( backbeatRoutes , 'GET' ) . returns ( {
770- metadata : sinon . stub ( ) ,
771- multiplebackendmetadata : sinon . stub ( ) ,
772- lifecycle : sinon . stub ( ) ,
773- index : sinon . stub ( ) ,
774- } ) ;
740+ // create a Promise that resolves when response.end is called
741+ endPromise = new Promise ( resolve => { resolveEnd = resolve ; } ) ;
775742
776743 request = new DummyRequest (
777744 {
@@ -784,7 +751,10 @@ describe('routeBackbeat authorization', () => {
784751 response = {
785752 setHeader : sinon . stub ( ) ,
786753 writeHead : sinon . stub ( ) ,
787- end : sinon . stub ( ) ,
754+ end : sinon . stub ( ) . callsFake ( ( body , encoding , callback ) => {
755+ resolveEnd ( ) ;
756+ callback ( ) ;
757+ } )
788758 } ;
789759 } ) ;
790760
@@ -953,74 +923,117 @@ describe('routeBackbeat authorization', () => {
953923 expect : errors . NotImplemented ,
954924 }
955925 ] . forEach ( testCase => {
956- it ( `should call method ${ testCase . method } ${ testCase . resourceType } ` , done => {
957- let hasQuery = false ;
926+ describe ( `${ testCase . method } ${ testCase . resourceType } ` , ( ) => {
958927 let versionIdParsed = null ;
959- request . method = testCase . method ;
960- request . url = `/_/backbeat/${ testCase . resourceType } /${ testCase . target } ` ;
961- if ( testCase . operation ) {
962- request . url += `?operation=${ testCase . operation } ` ;
963- hasQuery = true ;
964- }
965-
966- // Mock auth server to ignore auth in this test
967- sinon . stub ( auth . server , 'doAuth' ) . callsFake ( ( req , log , cb ) =>
968- cb ( null , new AuthInfo ( {
928+ let hasQuery = false ;
929+
930+ beforeEach ( done => {
931+ hasQuery = false ;
932+ versionIdParsed = null ;
933+ request . method = testCase . method ;
934+ request . url = `/_/backbeat/${ testCase . resourceType } /${ testCase . target } ` ;
935+ if ( testCase . operation ) {
936+ request . url += `?operation=${ testCase . operation } ` ;
937+ hasQuery = true ;
938+ }
939+
940+ const enableVersioningRequest =
941+ versioningTestUtils . createBucketPutVersioningReq ( bucketName , 'Enabled' ) ;
942+
943+ return async . series ( [
944+ next => bucketPut ( authInfo , testBucket , log , next ) ,
945+ next => bucketPutVersioning ( authInfo , enableVersioningRequest , log , next ) ,
946+ next => objectPut ( authInfo , testObject , undefined , log , ( err , res ) => {
947+ if ( ! err && res ) {
948+ versionIdParsed = res [ 'x-amz-version-id' ] ;
949+ if ( testCase . versionId ) {
950+ request . url += `${ ( hasQuery ? '&' : '?' ) } &versionId=${ versionIdParsed } ` ;
951+ }
952+ }
953+ next ( err ) ;
954+ } ) ,
955+ ] , done ) ;
956+ } ) ;
957+
958+ afterEach ( done => {
959+ async . series ( [
960+ next => {
961+ const deleteRequest = {
962+ bucketName,
963+ objectKey : objectName ,
964+ headers : { } ,
965+ query : versionIdParsed ? { versionId : versionIdParsed } : { } ,
966+ } ;
967+ objectDelete ( authInfo , deleteRequest , log , next ) ;
968+ } ,
969+ next => {
970+ bucketDelete ( authInfo , testBucket , log , next ) ;
971+ }
972+ ] , done ) ;
973+ } ) ;
974+
975+ it ( 'should call method successfully' , async ( ) => {
976+ // Mock auth server to ignore auth in this test
977+ sinon . stub ( auth . server , 'doAuth' ) . yields ( null , new AuthInfo ( {
969978 canonicalID : 'abcdef/lifecycle' ,
970979 accountDisplayName : 'Lifecycle Service Account' ,
971980 } ) , undefined , undefined , {
972981 accountQuota : 1000 ,
973- } )
974- ) ;
982+ } ) ;
975983
976- const enableVersioningRequest =
977- versioningTestUtils . createBucketPutVersioningReq ( bucketName , 'Enabled' ) ;
984+ routeBackbeat ( '127.0.0.1' , request , response , log ) ;
985+
986+ void await endPromise ;
978987
979- response . end . callsFake ( ( body , format , cb ) => {
980988 if ( testCase . expect ) {
981989 const errCode = response . writeHead . getCall ( 0 ) . args [ 0 ] ;
982990 assert . strictEqual ( errCode , testCase . expect . code ) ;
983- cb ( ) ;
984- return done ( ) ;
985991 }
986992 assert . strictEqual ( Array . isArray ( request . finalizerHooks ) , true ) ;
987993 assert . strictEqual ( request . apiMethods [ 0 ] , 'objectReplicate' ) ;
988994 assert . strictEqual ( request . apiMethods . length , 1 ) ;
989995 assert . strictEqual ( request . accountQuotas , 1000 ) ;
990- cb ( ) ;
991- return done ( ) ;
992996 } ) ;
993997
994- return async . series ( [
995- next => bucketPut ( authInfo , testBucket , log , next ) ,
996- next => bucketPutVersioning ( authInfo , enableVersioningRequest , log , next ) ,
997- next => objectPut ( authInfo , testObject , undefined , log , ( err , res ) => {
998- versionIdParsed = res [ 'x-amz-version-id' ] ;
999- if ( testCase . versionId ) {
1000- request . url += `${ ( hasQuery ? '&' : '?' ) } &versionId=${ versionIdParsed } ` ;
1001- }
1002- next ( err ) ;
1003- } ) ,
1004- next => routeBackbeat ( '127.0.0.1' , request , response , log , next ) ,
1005- ] , err => {
1006- assert . ifError ( err ) ;
998+ it ( 'should return access denied user is not authorized' , async ( ) => {
999+ sinon . stub ( auth . server , 'doAuth' ) . yields ( null , new AuthInfo ( {
1000+ canonicalID : '123456789' ,
1001+ accountDisplayName : 'user1' ,
1002+ } ) , [ {
1003+ isAllowed : false ,
1004+ implicitDeny : true ,
1005+ action : 'objectReplicate' ,
1006+ } ] , undefined , undefined ) ;
1007+
1008+ routeBackbeat ( '127.0.0.1' , request , response , log ) ;
1009+
1010+ void await endPromise ;
1011+
1012+ const err = JSON . parse ( response . end . getCall ( 0 ) . args [ 0 ] ) ;
1013+ assert . strictEqual ( err . code , 'AccessDenied' ) ;
10071014 } ) ;
1008- } ) ;
1009- } ) ;
10101015
1011- // Although the authz result is by default an implicit deny, the
1012- // ACL should prevent any further processing for non-service or
1013- // non-account identities.
1014- it ( 'should return access denied if doAuth returns an error' , done => {
1015- request . method = 'PUT' ;
1016- request . url = `/_/backbeat/metadata/${ bucketName } /${ objectName } ?operation=putobject` ;
1017- response . end . callsFake ( ( body , format , cb ) => {
1018- const err = JSON . parse ( response . end . getCall ( 0 ) . args [ 0 ] ) ;
1019- assert . strictEqual ( err . code , 'AccessDenied' ) ;
1020- cb ( ) ;
1021- return done ( ) ;
1022- } ) ;
1016+ it ( 'should bypass policy evaluation' , async ( ) => {
1017+ sinon . stub ( auth . server , 'doAuth' ) . yields ( null , new AuthInfo ( {
1018+ canonicalID : 'abcdef/lifecycle' ,
1019+ accountDisplayName : 'Lifecycle Service Account' ,
1020+ } ) , [ {
1021+ isAllowed : false ,
1022+ implicitDeny : true ,
1023+ action : 'objectReplicate' ,
1024+ } ] , undefined , undefined ) ;
10231025
1024- routeBackbeat ( '127.0.0.1' , request , response , log ) ;
1026+ request . bypassUserBucketPolicies = true ;
1027+
1028+ routeBackbeat ( '127.0.0.1' , request , response , log ) ;
1029+
1030+ void await endPromise ;
1031+
1032+ if ( testCase . expect ) {
1033+ const errCode = response . writeHead . getCall ( 0 ) . args [ 0 ] ;
1034+ assert . strictEqual ( errCode , testCase . expect . code ) ;
1035+ }
1036+ } ) ;
1037+ } ) ;
10251038 } ) ;
10261039} ) ;
0 commit comments