11const middlewares = require ( '../lib/middlewares' ) ;
22const AppCache = require ( '../lib/cache' ) . AppCache ;
3+ const { BlockList } = require ( 'net' ) ;
4+
5+ const AppCachePut = ( appId , config ) =>
6+ AppCache . put ( appId , {
7+ ...config ,
8+ maintenanceKeyIpsStore : new Map ( ) ,
9+ masterKeyIpsStore : new Map ( ) ,
10+ } ) ;
311
412describe ( 'middlewares' , ( ) => {
513 let fakeReq , fakeRes ;
614 beforeEach ( ( ) => {
715 fakeReq = {
16+ ip : '127.0.0.1' ,
817 originalUrl : 'http://example.com/parse/' ,
918 url : 'http://example.com/' ,
1019 body : {
@@ -16,7 +25,7 @@ describe('middlewares', () => {
1625 } ,
1726 } ;
1827 fakeRes = jasmine . createSpyObj ( 'fakeRes' , [ 'end' , 'status' ] ) ;
19- AppCache . put ( fakeReq . body . _ApplicationId , { } ) ;
28+ AppCachePut ( fakeReq . body . _ApplicationId , { } ) ;
2029 } ) ;
2130
2231 afterEach ( ( ) => {
@@ -35,7 +44,7 @@ describe('middlewares', () => {
3544 } ) ;
3645
3746 it ( 'should give invalid response when keys are configured but no key supplied' , ( ) => {
38- AppCache . put ( fakeReq . body . _ApplicationId , {
47+ AppCachePut ( fakeReq . body . _ApplicationId , {
3948 masterKey : 'masterKey' ,
4049 restAPIKey : 'restAPIKey' ,
4150 } ) ;
@@ -44,7 +53,7 @@ describe('middlewares', () => {
4453 } ) ;
4554
4655 it ( 'should give invalid response when keys are configured but supplied key is incorrect' , ( ) => {
47- AppCache . put ( fakeReq . body . _ApplicationId , {
56+ AppCachePut ( fakeReq . body . _ApplicationId , {
4857 masterKey : 'masterKey' ,
4958 restAPIKey : 'restAPIKey' ,
5059 } ) ;
@@ -54,7 +63,7 @@ describe('middlewares', () => {
5463 } ) ;
5564
5665 it ( 'should give invalid response when keys are configured but different key is supplied' , ( ) => {
57- AppCache . put ( fakeReq . body . _ApplicationId , {
66+ AppCachePut ( fakeReq . body . _ApplicationId , {
5867 masterKey : 'masterKey' ,
5968 restAPIKey : 'restAPIKey' ,
6069 } ) ;
@@ -64,7 +73,7 @@ describe('middlewares', () => {
6473 } ) ;
6574
6675 it ( 'should succeed when any one of the configured keys supplied' , done => {
67- AppCache . put ( fakeReq . body . _ApplicationId , {
76+ AppCachePut ( fakeReq . body . _ApplicationId , {
6877 clientKey : 'clientKey' ,
6978 masterKey : 'masterKey' ,
7079 restAPIKey : 'restAPIKey' ,
@@ -77,7 +86,7 @@ describe('middlewares', () => {
7786 } ) ;
7887
7988 it ( 'should succeed when client key supplied but empty' , done => {
80- AppCache . put ( fakeReq . body . _ApplicationId , {
89+ AppCachePut ( fakeReq . body . _ApplicationId , {
8190 clientKey : '' ,
8291 masterKey : 'masterKey' ,
8392 restAPIKey : 'restAPIKey' ,
@@ -90,7 +99,7 @@ describe('middlewares', () => {
9099 } ) ;
91100
92101 it ( 'should succeed when no keys are configured and none supplied' , done => {
93- AppCache . put ( fakeReq . body . _ApplicationId , {
102+ AppCachePut ( fakeReq . body . _ApplicationId , {
94103 masterKey : 'masterKey' ,
95104 } ) ;
96105 middlewares . handleParseHeaders ( fakeReq , fakeRes , ( ) => {
@@ -117,7 +126,7 @@ describe('middlewares', () => {
117126 otherKey => otherKey !== infoKey && otherKey !== 'javascriptKey'
118127 ) ;
119128 it ( `it should pull ${ bodyKey } into req.info` , done => {
120- AppCache . put ( fakeReq . body . _ApplicationId , {
129+ AppCachePut ( fakeReq . body . _ApplicationId , {
121130 masterKeyIps : [ '0.0.0.0/0' ] ,
122131 } ) ;
123132 fakeReq . ip = '127.0.0.1' ;
@@ -138,7 +147,7 @@ describe('middlewares', () => {
138147 it ( 'should not succeed and log if the ip does not belong to masterKeyIps list' , async ( ) => {
139148 const logger = require ( '../lib/logger' ) . logger ;
140149 spyOn ( logger , 'error' ) . and . callFake ( ( ) => { } ) ;
141- AppCache . put ( fakeReq . body . _ApplicationId , {
150+ AppCachePut ( fakeReq . body . _ApplicationId , {
142151 masterKey : 'masterKey' ,
143152 masterKeyIps : [ '10.0.0.1' ] ,
144153 } ) ;
@@ -152,7 +161,7 @@ describe('middlewares', () => {
152161 } ) ;
153162
154163 it ( 'should not succeed if the ip does not belong to masterKeyIps list' , async ( ) => {
155- AppCache . put ( fakeReq . body . _ApplicationId , {
164+ AppCachePut ( fakeReq . body . _ApplicationId , {
156165 masterKey : 'masterKey' ,
157166 masterKeyIps : [ '10.0.0.1' ] ,
158167 } ) ;
@@ -165,7 +174,7 @@ describe('middlewares', () => {
165174 it ( 'should not succeed if the ip does not belong to maintenanceKeyIps list' , async ( ) => {
166175 const logger = require ( '../lib/logger' ) . logger ;
167176 spyOn ( logger , 'error' ) . and . callFake ( ( ) => { } ) ;
168- AppCache . put ( fakeReq . body . _ApplicationId , {
177+ AppCachePut ( fakeReq . body . _ApplicationId , {
169178 maintenanceKey : 'masterKey' ,
170179 maintenanceKeyIps : [ '10.0.0.0' , '10.0.0.1' ] ,
171180 } ) ;
@@ -179,7 +188,7 @@ describe('middlewares', () => {
179188 } ) ;
180189
181190 it ( 'should succeed if the ip does belong to masterKeyIps list' , async ( ) => {
182- AppCache . put ( fakeReq . body . _ApplicationId , {
191+ AppCachePut ( fakeReq . body . _ApplicationId , {
183192 masterKey : 'masterKey' ,
184193 masterKeyIps : [ '10.0.0.1' ] ,
185194 } ) ;
@@ -190,7 +199,7 @@ describe('middlewares', () => {
190199 } ) ;
191200
192201 it ( 'should allow any ip to use masterKey if masterKeyIps is empty' , async ( ) => {
193- AppCache . put ( fakeReq . body . _ApplicationId , {
202+ AppCachePut ( fakeReq . body . _ApplicationId , {
194203 masterKey : 'masterKey' ,
195204 masterKeyIps : [ '0.0.0.0/0' ] ,
196205 } ) ;
@@ -221,7 +230,7 @@ describe('middlewares', () => {
221230 } ) ;
222231
223232 it ( 'should set default Access-Control-Allow-Headers if allowHeaders are empty' , ( ) => {
224- AppCache . put ( fakeReq . body . _ApplicationId , {
233+ AppCachePut ( fakeReq . body . _ApplicationId , {
225234 allowHeaders : undefined ,
226235 } ) ;
227236 const headers = { } ;
@@ -234,15 +243,15 @@ describe('middlewares', () => {
234243 allowCrossDomain ( fakeReq , res , ( ) => { } ) ;
235244 expect ( headers [ 'Access-Control-Allow-Headers' ] ) . toContain ( middlewares . DEFAULT_ALLOWED_HEADERS ) ;
236245
237- AppCache . put ( fakeReq . body . _ApplicationId , {
246+ AppCachePut ( fakeReq . body . _ApplicationId , {
238247 allowHeaders : [ ] ,
239248 } ) ;
240249 allowCrossDomain ( fakeReq , res , ( ) => { } ) ;
241250 expect ( headers [ 'Access-Control-Allow-Headers' ] ) . toContain ( middlewares . DEFAULT_ALLOWED_HEADERS ) ;
242251 } ) ;
243252
244253 it ( 'should append custom headers to Access-Control-Allow-Headers if allowHeaders provided' , ( ) => {
245- AppCache . put ( fakeReq . body . _ApplicationId , {
254+ AppCachePut ( fakeReq . body . _ApplicationId , {
246255 allowHeaders : [ 'Header-1' , 'Header-2' ] ,
247256 } ) ;
248257 const headers = { } ;
@@ -258,7 +267,7 @@ describe('middlewares', () => {
258267 } ) ;
259268
260269 it ( 'should set default Access-Control-Allow-Origin if allowOrigin is empty' , ( ) => {
261- AppCache . put ( fakeReq . body . _ApplicationId , {
270+ AppCachePut ( fakeReq . body . _ApplicationId , {
262271 allowOrigin : undefined ,
263272 } ) ;
264273 const headers = { } ;
@@ -273,7 +282,7 @@ describe('middlewares', () => {
273282 } ) ;
274283
275284 it ( 'should set custom origin to Access-Control-Allow-Origin if allowOrigin is provided' , ( ) => {
276- AppCache . put ( fakeReq . body . _ApplicationId , {
285+ AppCachePut ( fakeReq . body . _ApplicationId , {
277286 allowOrigin : 'https://parseplatform.org/' ,
278287 } ) ;
279288 const headers = { } ;
@@ -317,7 +326,7 @@ describe('middlewares', () => {
317326 } ) ;
318327
319328 it ( 'should use user provided on field userFromJWT' , done => {
320- AppCache . put ( fakeReq . body . _ApplicationId , {
329+ AppCachePut ( fakeReq . body . _ApplicationId , {
321330 masterKey : 'masterKey' ,
322331 } ) ;
323332 fakeReq . userFromJWT = 'fake-user' ;
@@ -328,11 +337,87 @@ describe('middlewares', () => {
328337 } ) ;
329338
330339 it ( 'should give invalid response when upload file without x-parse-application-id in header' , ( ) => {
331- AppCache . put ( fakeReq . body . _ApplicationId , {
340+ AppCachePut ( fakeReq . body . _ApplicationId , {
332341 masterKey : 'masterKey' ,
333342 } ) ;
334343 fakeReq . body = Buffer . from ( 'fake-file' ) ;
335344 middlewares . handleParseHeaders ( fakeReq , fakeRes ) ;
336345 expect ( fakeRes . status ) . toHaveBeenCalledWith ( 403 ) ;
337346 } ) ;
347+
348+ it ( 'should match address' , ( ) => {
349+ const ipv6 = '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ;
350+ const anotherIpv6 = '::ffff:101.10.0.1' ;
351+ const ipv4 = '192.168.0.101' ;
352+ const localhostV6 = '::1' ;
353+ const localhostV62 = '::ffff:127.0.0.1' ;
354+ const localhostV4 = '127.0.0.1' ;
355+
356+ const v6 = [ ipv6 , anotherIpv6 ] ;
357+ v6 . forEach ( ip => {
358+ expect ( middlewares . checkIp ( ip , [ '::/0' ] , new Map ( ) ) ) . toBe ( true ) ;
359+ expect ( middlewares . checkIp ( ip , [ '::' ] , new Map ( ) ) ) . toBe ( true ) ;
360+ expect ( middlewares . checkIp ( ip , [ '0.0.0.0' ] , new Map ( ) ) ) . toBe ( false ) ;
361+ expect ( middlewares . checkIp ( ip , [ '0.0.0.0/0' ] , new Map ( ) ) ) . toBe ( false ) ;
362+ expect ( middlewares . checkIp ( ip , [ '123.123.123.123' ] , new Map ( ) ) ) . toBe ( false ) ;
363+ } ) ;
364+
365+ expect ( middlewares . checkIp ( ipv6 , [ anotherIpv6 ] , new Map ( ) ) ) . toBe ( false ) ;
366+ expect ( middlewares . checkIp ( ipv6 , [ ipv6 ] , new Map ( ) ) ) . toBe ( true ) ;
367+ expect ( middlewares . checkIp ( ipv6 , [ '2001:db8:85a3:0:0:8a2e:0:0/100' ] , new Map ( ) ) ) . toBe ( true ) ;
368+
369+ expect ( middlewares . checkIp ( ipv4 , [ '::' ] , new Map ( ) ) ) . toBe ( false ) ;
370+ expect ( middlewares . checkIp ( ipv4 , [ '::/0' ] , new Map ( ) ) ) . toBe ( false ) ;
371+ expect ( middlewares . checkIp ( ipv4 , [ '0.0.0.0' ] , new Map ( ) ) ) . toBe ( true ) ;
372+ expect ( middlewares . checkIp ( ipv4 , [ '0.0.0.0/0' ] , new Map ( ) ) ) . toBe ( true ) ;
373+ expect ( middlewares . checkIp ( ipv4 , [ '123.123.123.123' ] , new Map ( ) ) ) . toBe ( false ) ;
374+ expect ( middlewares . checkIp ( ipv4 , [ ipv4 ] , new Map ( ) ) ) . toBe ( true ) ;
375+ expect ( middlewares . checkIp ( ipv4 , [ '192.168.0.0/24' ] , new Map ( ) ) ) . toBe ( true ) ;
376+
377+ expect ( middlewares . checkIp ( localhostV4 , [ '::1' ] , new Map ( ) ) ) . toBe ( false ) ;
378+ expect ( middlewares . checkIp ( localhostV6 , [ '::1' ] , new Map ( ) ) ) . toBe ( true ) ;
379+ // ::ffff:127.0.0.1 is a padded ipv4 address but not ::1
380+ expect ( middlewares . checkIp ( localhostV62 , [ '::1' ] , new Map ( ) ) ) . toBe ( false ) ;
381+ // ::ffff:127.0.0.1 is a padded ipv4 address and is a match for 127.0.0.1
382+ expect ( middlewares . checkIp ( localhostV62 , [ '127.0.0.1' ] , new Map ( ) ) ) . toBe ( true ) ;
383+ } ) ;
384+
385+ it ( 'should match address with cache' , ( ) => {
386+ const ipv6 = '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ;
387+ const cache1 = new Map ( ) ;
388+ const spyBlockListCheck = spyOn ( BlockList . prototype , 'check' ) . and . callThrough ( ) ;
389+ expect ( middlewares . checkIp ( ipv6 , [ '::' ] , cache1 ) ) . toBe ( true ) ;
390+ expect ( cache1 . get ( '2001:0db8:85a3:0000:0000:8a2e:0370:7334' ) ) . toBe ( undefined ) ;
391+ expect ( cache1 . get ( 'allowAllIpv6' ) ) . toBe ( true ) ;
392+ expect ( spyBlockListCheck ) . toHaveBeenCalledTimes ( 0 ) ;
393+
394+ const cache2 = new Map ( ) ;
395+ expect ( middlewares . checkIp ( '::1' , [ '::1' ] , cache2 ) ) . toBe ( true ) ;
396+ expect ( cache2 . get ( '::1' ) ) . toBe ( true ) ;
397+ expect ( spyBlockListCheck ) . toHaveBeenCalledTimes ( 1 ) ;
398+ expect ( middlewares . checkIp ( '::1' , [ '::1' ] , cache2 ) ) . toBe ( true ) ;
399+ expect ( spyBlockListCheck ) . toHaveBeenCalledTimes ( 1 ) ;
400+ spyBlockListCheck . calls . reset ( ) ;
401+
402+ const cache3 = new Map ( ) ;
403+ expect ( middlewares . checkIp ( '127.0.0.1' , [ '127.0.0.1' ] , cache3 ) ) . toBe ( true ) ;
404+ expect ( cache3 . get ( '127.0.0.1' ) ) . toBe ( true ) ;
405+ expect ( spyBlockListCheck ) . toHaveBeenCalledTimes ( 1 ) ;
406+ expect ( middlewares . checkIp ( '127.0.0.1' , [ '127.0.0.1' ] , cache3 ) ) . toBe ( true ) ;
407+ expect ( spyBlockListCheck ) . toHaveBeenCalledTimes ( 1 ) ;
408+ spyBlockListCheck . calls . reset ( ) ;
409+
410+ const cache4 = new Map ( ) ;
411+ const ranges = [ '127.0.0.1' , '192.168.0.0/24' ] ;
412+ // should not cache negative match
413+ expect ( middlewares . checkIp ( '123.123.123.123' , ranges , cache4 ) ) . toBe ( false ) ;
414+ expect ( cache4 . get ( '123.123.123.123' ) ) . toBe ( undefined ) ;
415+ expect ( spyBlockListCheck ) . toHaveBeenCalledTimes ( 1 ) ;
416+ spyBlockListCheck . calls . reset ( ) ;
417+
418+ // should not cache cidr
419+ expect ( middlewares . checkIp ( '192.168.0.101' , ranges , cache4 ) ) . toBe ( true ) ;
420+ expect ( cache4 . get ( '192.168.0.101' ) ) . toBe ( undefined ) ;
421+ expect ( spyBlockListCheck ) . toHaveBeenCalledTimes ( 1 ) ;
422+ } ) ;
338423} ) ;
0 commit comments