@@ -5,6 +5,8 @@ const { assert } = require('chai')
5
5
const getPort = require ( 'get-port' )
6
6
const path = require ( 'path' )
7
7
const semver = require ( 'semver' )
8
+ const zlib = require ( 'zlib' )
9
+ const fs = require ( 'node:fs' )
8
10
const agent = require ( '../plugins/agent' )
9
11
const appsec = require ( '../../src/appsec' )
10
12
const Config = require ( '../../src/config' )
@@ -167,11 +169,12 @@ withVersions('fastify', 'fastify', version => {
167
169
assert . deepEqual ( e . response . data , JSON . parse ( json ) )
168
170
sinon . assert . notCalled ( requestBody )
169
171
170
- await agent . assertSomeTraces ( ( traces ) => {
171
- const span = traces [ 0 ] [ 0 ]
172
- assert . equal ( span . metrics [ '_dd.appsec.truncated.string_length' ] , 5000 )
173
- assert . equal ( span . metrics [ '_dd.appsec.truncated.container_size' ] , 300 )
174
- assert . equal ( span . metrics [ '_dd.appsec.truncated.container_depth' ] , 20 )
172
+ await agent . assertFirstTraceSpan ( {
173
+ metrics : {
174
+ '_dd.appsec.truncated.string_length' : 5000 ,
175
+ '_dd.appsec.truncated.container_size' : 300 ,
176
+ '_dd.appsec.truncated.container_depth' : 20
177
+ }
175
178
} )
176
179
}
177
180
} )
@@ -446,6 +449,159 @@ withVersions('fastify', 'fastify', version => {
446
449
} )
447
450
} )
448
451
452
+ describe ( 'Api Security - Fastify' , ( ) => {
453
+ withVersions ( 'fastify' , 'fastify' , version => {
454
+ let config , server , axios
455
+
456
+ before ( ( ) => {
457
+ return agent . load ( [ 'fastify' , 'http' ] , { client : false } )
458
+ } )
459
+
460
+ before ( ( done ) => {
461
+ const fastify = require ( `../../../../versions/fastify@${ version } ` ) . get ( )
462
+
463
+ const app = fastify ( )
464
+
465
+ app . post ( '/send' , ( request , reply ) => {
466
+ reply . send ( { sendResKey : 'sendResValue' } )
467
+ } )
468
+
469
+ app . post ( '/return' , async ( request , reply ) => {
470
+ return { returnResKey : 'returnResValue' }
471
+ } )
472
+
473
+ app . get ( '/' , ( request , reply ) => {
474
+ reply . send ( 'DONE' )
475
+ } )
476
+
477
+ app . get ( '/buffer' , ( request , reply ) => {
478
+ reply . send ( Buffer . from ( 'DONE' ) )
479
+ } )
480
+
481
+ app . get ( '/stream' , ( request , reply ) => {
482
+ const stream = fs . createReadStream ( __filename )
483
+ reply . header ( 'Content-Type' , 'application/octet-stream' )
484
+ reply . send ( stream )
485
+ } )
486
+
487
+ app . get ( '/typedarray' , ( request , reply ) => {
488
+ reply . send ( new Uint16Array ( 10 ) )
489
+ } )
490
+
491
+ getPort ( ) . then ( ( port ) => {
492
+ app . listen ( { port } , ( ) => {
493
+ axios = Axios . create ( { baseURL : `http://localhost:${ port } ` } )
494
+ done ( )
495
+ } )
496
+ server = app . server
497
+ } )
498
+ } )
499
+
500
+ after ( ( ) => {
501
+ server . close ( )
502
+ return agent . close ( { ritmReset : false } )
503
+ } )
504
+
505
+ beforeEach ( ( ) => {
506
+ config = new Config ( {
507
+ appsec : {
508
+ enabled : true ,
509
+ rules : path . join ( __dirname , 'api_security_rules.json' ) ,
510
+ apiSecurity : {
511
+ enabled : true ,
512
+ sampleDelay : 10
513
+ }
514
+ }
515
+ } )
516
+ appsec . enable ( config )
517
+ } )
518
+
519
+ afterEach ( ( ) => {
520
+ appsec . disable ( )
521
+ } )
522
+
523
+ function formatSchema ( body ) {
524
+ return zlib . gzipSync ( JSON . stringify ( body ) ) . toString ( 'base64' )
525
+ }
526
+
527
+ it ( 'should get the response body schema with reply.send' , async ( ) => {
528
+ const expectedResponseBodySchema = formatSchema ( [ { sendResKey : [ 8 ] } ] )
529
+ const res = await axios . post ( '/send' , { key : 'value' } )
530
+
531
+ await agent . assertFirstTraceSpan ( {
532
+ meta : {
533
+ '_dd.appsec.s.res.body' : expectedResponseBodySchema
534
+ }
535
+ } )
536
+
537
+ assert . equal ( res . status , 200 )
538
+ assert . deepEqual ( res . data , { sendResKey : 'sendResValue' } )
539
+ } )
540
+
541
+ it ( 'should get the response body schema with return' , async ( ) => {
542
+ const expectedResponseBodySchema = formatSchema ( [ { returnResKey : [ 8 ] } ] )
543
+ const res = await axios . post ( '/return' , { key : 'value' } )
544
+
545
+ await agent . assertFirstTraceSpan ( {
546
+ meta : {
547
+ '_dd.appsec.s.res.body' : expectedResponseBodySchema
548
+ }
549
+ } )
550
+
551
+ assert . equal ( res . status , 200 )
552
+ assert . deepEqual ( res . data , { returnResKey : 'returnResValue' } )
553
+ } )
554
+
555
+ it ( 'should not get the schema for string' , async ( ) => {
556
+ const res = await axios . get ( '/' )
557
+
558
+ await agent . assertFirstTraceSpan ( span => {
559
+ assert . notProperty ( span . meta , '_dd.appsec.s.res.body' )
560
+ } )
561
+
562
+ assert . equal ( res . status , 200 )
563
+ assert . equal ( res . data , 'DONE' )
564
+ } )
565
+
566
+ it ( 'should not get the schema for Buffer' , async ( ) => {
567
+ const res = await axios . get ( '/buffer' )
568
+
569
+ await agent . assertFirstTraceSpan ( span => {
570
+ if ( span . meta ) {
571
+ assert . notProperty ( span . meta , '_dd.appsec.s.res.body' )
572
+ }
573
+ } )
574
+
575
+ assert . equal ( res . status , 200 )
576
+ assert . equal ( res . data , 'DONE' )
577
+ } )
578
+
579
+ it ( 'should not get the schema for stream' , async ( ) => {
580
+ const res = await axios . get ( '/stream' , { responseType : 'arraybuffer' } )
581
+
582
+ await agent . assertFirstTraceSpan ( span => {
583
+ if ( span . meta ) {
584
+ assert . notProperty ( span . meta , '_dd.appsec.s.res.body' )
585
+ }
586
+ } )
587
+
588
+ assert . equal ( res . status , 200 )
589
+ } )
590
+
591
+ it ( 'should not get the schema for TypedArray' , async ( ) => {
592
+ const res = await axios . get ( '/typedarray' , { responseType : 'arraybuffer' } )
593
+
594
+ await agent . assertFirstTraceSpan ( span => {
595
+ if ( span . meta ) {
596
+ assert . notProperty ( span . meta , '_dd.appsec.s.res.body' )
597
+ }
598
+ } )
599
+
600
+ assert . equal ( res . status , 200 )
601
+ } )
602
+ } )
603
+ } )
604
+
449
605
const createNestedObject = ( n , obj ) => {
450
606
if ( n > 0 ) {
451
607
return { a : createNestedObject ( n - 1 , obj ) }
0 commit comments