@@ -913,6 +913,65 @@ class TelemetryTests {
913913 assert ' rate_limited:false' in wafReq. tags
914914 }
915915
916+
917+ /**
918+ * Verifies that appsec.waf.requests is tagged request_blocked:true when the WAF
919+ * returns a block_request action and false otherwise
920+ */
921+ @Test
922+ @Order (10 )
923+ void ' waf requests request_blocked tag is true on blocking attack' () {
924+ Assumptions . assumeTrue(System . getProperty(' USE_HELPER_RUST' ) != null ,
925+ ' request_blocked tag is only emitted unconditionally by the Rust helper' )
926+
927+ Supplier<RemoteConfigRequest > requestSup = CONTAINER . applyRemoteConfig(RC_TARGET , [
928+ ' datadog/2/ASM_FEATURES/asm_features_activation/config' : [
929+ asm : [enabled : true ]
930+ ]
931+ ])
932+
933+ CONTAINER . traceFromRequest(' /hello.php' ) { HttpResponse<InputStream > resp ->
934+ assert resp. statusCode() == 200
935+ }
936+ assert requestSup. get() != null
937+
938+ // Blocking request: 80.80.80.80 hits the recommended.json IP blocklist rule
939+ // (on_match: ["block"]). The WAF returns a block_request action.
940+ HttpRequest req = CONTAINER . buildReq(' /hello.php' )
941+ .header(' X-Forwarded-For' , ' 80.80.80.80' ). GET (). build()
942+ CONTAINER . traceFromRequest(req, ofString()) { HttpResponse<String > resp ->
943+ assert resp. statusCode() == 403
944+ }
945+
946+ TelemetryHelpers.Metric wafReqBlocked
947+ TelemetryHelpers.Metric wafReqNotBlocked
948+
949+ TelemetryHelpers . waitForMetrics(CONTAINER , 30 ) { List<TelemetryHelpers.GenerateMetrics > messages ->
950+ def allSeries = messages. collectMany { it. series }
951+ wafReqBlocked = allSeries. find {
952+ it. name == ' waf.requests' &&
953+ ' rule_triggered:true' in it. tags &&
954+ ' request_blocked:true' in it. tags
955+ }
956+ // from the 1st request
957+ wafReqNotBlocked = allSeries. find {
958+ it. name == ' waf.requests' && ' request_blocked:false' in it. tags
959+ }
960+ wafReqBlocked != null && wafReqNotBlocked != null
961+ }
962+
963+ assert wafReqBlocked != null : ' waf.requests metric with request_blocked:true not found ' +
964+ ' -- helper failed to detect the WAF block action'
965+ assert wafReqBlocked. namespace == ' appsec'
966+ assert wafReqBlocked. type == ' count'
967+ assert ' rule_triggered:true' in wafReqBlocked. tags
968+ assert ' request_blocked:true' in wafReqBlocked. tags
969+
970+ assert wafReqNotBlocked != null : ' waf.requests metric with request_blocked:false not found ' +
971+ ' -- rust helper must emit request_blocked:false on non-blocked requests (RFC-1012)'
972+ assert ' request_blocked:false' in wafReqNotBlocked. tags
973+ }
974+
916975 /**
917976 * Verifies that _dd.appsec.rasp.duration (ms) and _dd.appsec.rasp.duration_ext (µs) are
918977 * emitted as span metrics and that appsec.rasp.duration / appsec.rasp.duration_ext are
0 commit comments