|
1 | 1 | package com.datadog.appsec.gateway; |
2 | 2 |
|
3 | 3 | import static com.datadog.appsec.event.data.MapDataBundle.Builder.CAPACITY_6_10; |
| 4 | +import static com.datadog.appsec.gateway.AppSecRequestContext.DEFAULT_REQUEST_HEADERS_ALLOW_LIST; |
| 5 | +import static com.datadog.appsec.gateway.AppSecRequestContext.HEADERS_ALLOW_LIST; |
4 | 6 |
|
5 | 7 | import com.datadog.appsec.AppSecSystem; |
6 | 8 | import com.datadog.appsec.api.security.ApiSecurityRequestSampler; |
|
31 | 33 | import datadog.trace.api.telemetry.WafMetricCollector; |
32 | 34 | import datadog.trace.bootstrap.instrumentation.api.Tags; |
33 | 35 | import datadog.trace.bootstrap.instrumentation.api.URIDataAdapter; |
34 | | -import datadog.trace.util.Strings; |
35 | 36 | import java.net.URI; |
36 | 37 | import java.net.URISyntaxException; |
37 | 38 | import java.nio.charset.Charset; |
@@ -130,51 +131,34 @@ public void init() { |
130 | 131 | pp.processTraceSegment(traceSeg, ctx, collectedEvents); |
131 | 132 | } |
132 | 133 |
|
133 | | - // If detected any events - mark span at appsec.event |
134 | | - if (!collectedEvents.isEmpty() && (rateLimiter == null || !rateLimiter.isThrottled())) { |
135 | | - // Keep event related span, because it could be ignored in case of |
136 | | - // reduced datadog sampling rate. |
137 | | - traceSeg.setTagTop(DDTags.MANUAL_KEEP, true); |
138 | | - traceSeg.setTagTop("appsec.event", true); |
139 | | - traceSeg.setTagTop("network.client.ip", ctx.getPeerAddress()); |
140 | | - |
141 | | - Map<String, List<String>> requestHeaders = ctx.getRequestHeaders(); |
142 | | - Map<String, List<String>> responseHeaders = ctx.getResponseHeaders(); |
143 | | - // Reflect client_ip as actor.ip for backward compatibility |
144 | | - Object clientIp = spanInfo.getTags().get(Tags.HTTP_CLIENT_IP); |
145 | | - if (clientIp != null) { |
146 | | - traceSeg.setTagTop("actor.ip", clientIp); |
147 | | - } |
148 | | - |
149 | | - // Report AppSec events via "_dd.appsec.json" tag |
150 | | - AppSecEventWrapper wrapper = new AppSecEventWrapper(collectedEvents); |
151 | | - traceSeg.setDataTop("appsec", wrapper); |
152 | | - |
153 | | - // Report collected request and response headers based on allow list |
154 | | - if (requestHeaders != null) { |
155 | | - requestHeaders.forEach( |
156 | | - (name, value) -> { |
157 | | - if (AppSecRequestContext.HEADERS_ALLOW_LIST.contains(name)) { |
158 | | - String v = Strings.join(",", value); |
159 | | - if (!v.isEmpty()) { |
160 | | - traceSeg.setTagTop("http.request.headers." + name, v); |
161 | | - } |
162 | | - } |
163 | | - }); |
164 | | - } |
165 | | - if (responseHeaders != null) { |
166 | | - responseHeaders.forEach( |
167 | | - (name, value) -> { |
168 | | - if (AppSecRequestContext.HEADERS_ALLOW_LIST.contains(name)) { |
169 | | - String v = String.join(",", value); |
170 | | - if (!v.isEmpty()) { |
171 | | - traceSeg.setTagTop("http.response.headers." + name, v); |
172 | | - } |
173 | | - } |
174 | | - }); |
| 134 | + if (rateLimiter == null || !rateLimiter.isThrottled()) { |
| 135 | + // If detected any events - mark span at appsec.event |
| 136 | + if (!collectedEvents.isEmpty()) { |
| 137 | + // Keep event related span, because it could be ignored in case of |
| 138 | + // reduced datadog sampling rate. |
| 139 | + traceSeg.setTagTop(DDTags.MANUAL_KEEP, true); |
| 140 | + traceSeg.setTagTop("appsec.event", true); |
| 141 | + traceSeg.setTagTop("network.client.ip", ctx.getPeerAddress()); |
| 142 | + |
| 143 | + // Reflect client_ip as actor.ip for backward compatibility |
| 144 | + Object clientIp = spanInfo.getTags().get(Tags.HTTP_CLIENT_IP); |
| 145 | + if (clientIp != null) { |
| 146 | + traceSeg.setTagTop("actor.ip", clientIp); |
| 147 | + } |
| 148 | + |
| 149 | + // Report AppSec events via "_dd.appsec.json" tag |
| 150 | + AppSecEventWrapper wrapper = new AppSecEventWrapper(collectedEvents); |
| 151 | + traceSeg.setDataTop("appsec", wrapper); |
| 152 | + |
| 153 | + // Report collected request and response headers based on allow list |
| 154 | + writeRequestHeaders(traceSeg, HEADERS_ALLOW_LIST, ctx.getRequestHeaders()); |
| 155 | + writeResponseHeaders(traceSeg, HEADERS_ALLOW_LIST, ctx.getResponseHeaders()); |
| 156 | + } else { |
| 157 | + // Report minimum set of collected request headers |
| 158 | + writeRequestHeaders( |
| 159 | + traceSeg, DEFAULT_REQUEST_HEADERS_ALLOW_LIST, ctx.getRequestHeaders()); |
175 | 160 | } |
176 | 161 | } |
177 | | - |
178 | 162 | // If extracted any Api Schemas - commit them |
179 | 163 | if (!ctx.commitApiSchemas(traceSeg)) { |
180 | 164 | log.debug("Unable to commit, api security schemas and will be skipped"); |
@@ -425,6 +409,38 @@ public void stop() { |
425 | 409 | subscriptionService.reset(); |
426 | 410 | } |
427 | 411 |
|
| 412 | + private static void writeRequestHeaders( |
| 413 | + final TraceSegment traceSeg, |
| 414 | + final Set<String> allowed, |
| 415 | + final Map<String, List<String>> headers) { |
| 416 | + writeHeaders(traceSeg, "http.request.headers.", allowed, headers); |
| 417 | + } |
| 418 | + |
| 419 | + private static void writeResponseHeaders( |
| 420 | + final TraceSegment traceSeg, |
| 421 | + final Set<String> allowed, |
| 422 | + final Map<String, List<String>> headers) { |
| 423 | + writeHeaders(traceSeg, "http.response.headers.", allowed, headers); |
| 424 | + } |
| 425 | + |
| 426 | + private static void writeHeaders( |
| 427 | + final TraceSegment traceSeg, |
| 428 | + final String prefix, |
| 429 | + final Set<String> allowed, |
| 430 | + final Map<String, List<String>> headers) { |
| 431 | + if (headers != null) { |
| 432 | + headers.forEach( |
| 433 | + (name, value) -> { |
| 434 | + if (allowed.contains(name)) { |
| 435 | + String v = String.join(",", value); |
| 436 | + if (!v.isEmpty()) { |
| 437 | + traceSeg.setTagTop(prefix + name, v); |
| 438 | + } |
| 439 | + } |
| 440 | + }); |
| 441 | + } |
| 442 | + } |
| 443 | + |
428 | 444 | private static class RequestContextSupplier implements Flow<AppSecRequestContext> { |
429 | 445 | private static final Flow<AppSecRequestContext> EMPTY = new RequestContextSupplier(null); |
430 | 446 |
|
|
0 commit comments