Skip to content

Commit 9fe0330

Browse files
authored
Merge pull request #3863 from DataDog/glopes/helper-rust-fix-blocked-tag
appsec/helper-rust: fix metric tag blocked_request
2 parents acb9b53 + c69d556 commit 9fe0330

2 files changed

Lines changed: 65 additions & 4 deletions

File tree

appsec/helper-rust/src/client/metrics.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,12 @@ impl RunOutputExt for libddwaf::RunOutput {
165165
}
166166
fn is_blocking(&self) -> bool {
167167
self.actions().is_some_and(|actions| {
168-
actions
169-
.value()
170-
.iter()
171-
.any(|action| matches!(action.key().to_str(), Some("block") | Some("redirect")))
168+
actions.value().iter().any(|action| {
169+
matches!(
170+
action.key().to_str(),
171+
Some("block_request") | Some("redirect_request")
172+
)
173+
})
172174
})
173175
}
174176
}

appsec/tests/integration/src/test/groovy/com/datadog/appsec/php/integration/TelemetryTests.groovy

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)