Skip to content

Commit fe3e325

Browse files
committed
Merge branch 'master' into ygree/snakeyaml-engine-migration
2 parents 84da741 + 0f42e0a commit fe3e325

File tree

20 files changed

+277
-76
lines changed

20 files changed

+277
-76
lines changed

.gitlab-ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ muzzle-dep-report:
377377
needs: [ build_tests ]
378378
stage: tests
379379
variables:
380-
KUBERNETES_MEMORY_REQUEST: 16Gi
381-
KUBERNETES_MEMORY_LIMIT: 16Gi
380+
KUBERNETES_MEMORY_REQUEST: 17Gi
381+
KUBERNETES_MEMORY_LIMIT: 17Gi
382382
KUBERNETES_CPU_REQUEST: 10
383383
GRADLE_WORKERS: 4
384384
GRADLE_MEM: 3G
@@ -402,7 +402,7 @@ muzzle-dep-report:
402402
export PROFILER_COMMAND="-XX:StartFlightRecording=settings=profile,filename=/tmp/${CI_JOB_NAME_SLUG}.jfr,dumponexit=true";
403403
fi
404404
- *prepare_test_env
405-
- export GRADLE_OPTS="-Dorg.gradle.jvmargs='-Xms$GRADLE_MEM -Xmx$GRADLE_MEM $PROFILER_COMMAND -XX:ErrorFile=/tmp/hs_err_pid%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp' -Ddatadog.forkedMaxHeapSize=768M -Ddatadog.forkedMinHeapSize=128M"
405+
- export GRADLE_OPTS="-Dorg.gradle.jvmargs='-Xms$GRADLE_MEM -Xmx$GRADLE_MEM $PROFILER_COMMAND -XX:ErrorFile=/tmp/hs_err_pid%p.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp' -Ddatadog.forkedMaxHeapSize=1024M -Ddatadog.forkedMinHeapSize=128M"
406406
- ./gradlew $GRADLE_TARGET $GRADLE_PARAMS -PtestJvm=$testJvm -PtaskPartitionCount=$NORMALIZED_NODE_TOTAL -PtaskPartition=$NORMALIZED_NODE_INDEX $GRADLE_ARGS --continue || $CONTINUE_ON_FAILURE
407407
after_script:
408408
- *restore_pretest_env

components/yaml/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
plugins {
2-
id("me.champeau.jmh")
2+
`java-library`
33
}
44

55
apply(from = "$rootDir/gradle/java.gradle")

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/decorator/HttpServerDecorator.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package datadog.trace.bootstrap.instrumentation.decorator;
22

3+
import static datadog.context.Context.root;
4+
import static datadog.context.propagation.Propagators.defaultPropagator;
35
import static datadog.trace.api.cache.RadixTreeCache.UNSET_STATUS;
46
import static datadog.trace.api.datastreams.DataStreamsContext.fromTags;
57
import static datadog.trace.api.gateway.Events.EVENTS;
@@ -8,6 +10,7 @@
810
import static datadog.trace.bootstrap.instrumentation.decorator.http.HttpResourceDecorator.HTTP_RESOURCE_DECORATOR;
911

1012
import datadog.appsec.api.blocking.BlockingException;
13+
import datadog.context.Context;
1114
import datadog.trace.api.Config;
1215
import datadog.trace.api.DDTags;
1316
import datadog.trace.api.function.TriConsumer;
@@ -124,6 +127,7 @@ protected AgentTracer.TracerAPI tracer() {
124127
return AgentTracer.get();
125128
}
126129

130+
/** Deprecated. Use {@link #extractContext(REQUEST_CARRIER)} instead. */
127131
public AgentSpanContext.Extracted extract(REQUEST_CARRIER carrier) {
128132
AgentPropagation.ContextVisitor<REQUEST_CARRIER> getter = getter();
129133
if (null == carrier || null == getter) {
@@ -132,7 +136,18 @@ public AgentSpanContext.Extracted extract(REQUEST_CARRIER carrier) {
132136
return extractContextAndGetSpanContext(carrier, getter);
133137
}
134138

135-
/** Deprecated. Use {@link #startSpan(String, Object, AgentSpanContext.Extracted)} instead. */
139+
/**
140+
* Will be renamed to #extract(REQUEST_CARRIER) when refactoring of instrumentation's is complete
141+
*/
142+
public Context extractContext(REQUEST_CARRIER carrier) {
143+
AgentPropagation.ContextVisitor<REQUEST_CARRIER> getter = getter();
144+
if (null == carrier || null == getter) {
145+
return root();
146+
}
147+
return defaultPropagator().extract(root(), carrier, getter);
148+
}
149+
150+
/** Deprecated. Use {@link #startSpanFromContext(String, Object, Context)} instead. */
136151
@Deprecated
137152
public AgentSpan startSpan(REQUEST_CARRIER carrier, AgentSpanContext.Extracted context) {
138153
return startSpan("http-server", carrier, context);
@@ -155,6 +170,20 @@ public AgentSpan startSpan(
155170
return span;
156171
}
157172

173+
/**
174+
* Will be renamed to #startSpan(String, REQUEST_CARRIER, Context) when refactoring of
175+
* instrumentation's is complete
176+
*/
177+
public AgentSpan startSpanFromContext(
178+
String instrumentationName, REQUEST_CARRIER carrier, Context context) {
179+
return startSpan(instrumentationName, carrier, getSpanContext(context));
180+
}
181+
182+
public AgentSpanContext.Extracted getSpanContext(Context context) {
183+
AgentSpan extractedSpan = AgentSpan.fromContext(context);
184+
return extractedSpan == null ? null : (AgentSpanContext.Extracted) extractedSpan.context();
185+
}
186+
158187
public AgentSpan onRequest(
159188
final AgentSpan span,
160189
final CONNECTION connection,

dd-java-agent/appsec/src/main/java/com/datadog/appsec/event/data/ObjectIntrospection.java

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.datadog.appsec.event.data;
22

3+
import com.datadog.appsec.gateway.AppSecRequestContext;
34
import datadog.trace.api.Platform;
5+
import datadog.trace.api.telemetry.WafMetricCollector;
46
import java.lang.reflect.Array;
57
import java.lang.reflect.Field;
68
import java.lang.reflect.InvocationTargetException;
@@ -16,6 +18,7 @@
1618
public final class ObjectIntrospection {
1719
private static final int MAX_DEPTH = 20;
1820
private static final int MAX_ELEMENTS = 256;
21+
private static final int MAX_STRING_LENGTH = 4096;
1922
private static final Logger log = LoggerFactory.getLogger(ObjectIntrospection.class);
2023

2124
private static final Method trySetAccessible;
@@ -60,20 +63,32 @@ private ObjectIntrospection() {}
6063
* <p>Certain instance fields are excluded. Right now, this includes metaClass fields in Groovy
6164
* objects and this$0 fields in inner classes.
6265
*
63-
* <p>Only string values are preserved. Numbers or booleans are removed, since we do not expect
64-
* rules to detect malicious payloads in these types. An exception to this are map keys, which are
65-
* always converted to strings.
66-
*
6766
* @param obj an arbitrary object
67+
* @param requestContext the request context
6868
* @return the converted object
6969
*/
70-
public static Object convert(Object obj) {
71-
return guardedConversion(obj, 0, new State());
70+
public static Object convert(Object obj, AppSecRequestContext requestContext) {
71+
State state = new State(requestContext);
72+
Object converted = guardedConversion(obj, 0, state);
73+
if (state.stringTooLong || state.listMapTooLarge || state.objectTooDeep) {
74+
requestContext.setWafTruncated();
75+
WafMetricCollector.get()
76+
.wafInputTruncated(state.stringTooLong, state.listMapTooLarge, state.objectTooDeep);
77+
}
78+
return converted;
7279
}
7380

7481
private static class State {
7582
int elemsLeft = MAX_ELEMENTS;
7683
int invalidKeyId;
84+
boolean objectTooDeep = false;
85+
boolean listMapTooLarge = false;
86+
boolean stringTooLong = false;
87+
AppSecRequestContext requestContext;
88+
89+
private State(AppSecRequestContext requestContext) {
90+
this.requestContext = requestContext;
91+
}
7792
}
7893

7994
private static Object guardedConversion(Object obj, int depth, State state) {
@@ -94,31 +109,48 @@ private static String keyConversion(Object key, State state) {
94109
return "null";
95110
}
96111
if (key instanceof String) {
97-
return (String) key;
112+
return checkStringLength((String) key, state);
98113
}
99114
if (key instanceof Number
100115
|| key instanceof Boolean
101116
|| key instanceof Character
102117
|| key instanceof CharSequence) {
103-
return key.toString();
118+
return checkStringLength(key.toString(), state);
104119
}
105120
return "invalid_key:" + (++state.invalidKeyId);
106121
}
107122

108123
private static Object doConversion(Object obj, int depth, State state) {
124+
if (obj == null) {
125+
return null;
126+
}
109127
state.elemsLeft--;
110-
if (state.elemsLeft <= 0 || obj == null || depth > MAX_DEPTH) {
128+
if (state.elemsLeft <= 0) {
129+
state.listMapTooLarge = true;
130+
return null;
131+
}
132+
133+
if (depth > MAX_DEPTH) {
134+
state.objectTooDeep = true;
111135
return null;
112136
}
113137

114-
// strings, booleans and numbers are preserved
115-
if (obj instanceof String || obj instanceof Boolean || obj instanceof Number) {
138+
// booleans and numbers are preserved
139+
if (obj instanceof Boolean || obj instanceof Number) {
116140
return obj;
117141
}
118142

143+
// strings are preserved, but we need to check the length
144+
if (obj instanceof String) {
145+
return checkStringLength((String) obj, state);
146+
}
147+
119148
// char sequences are transformed just in case they are not immutable,
149+
if (obj instanceof CharSequence) {
150+
return checkStringLength(obj.toString(), state);
151+
}
120152
// single char sequences are transformed to strings for ddwaf compatibility.
121-
if (obj instanceof CharSequence || obj instanceof Character) {
153+
if (obj instanceof Character) {
122154
return obj.toString();
123155
}
124156

@@ -147,6 +179,7 @@ private static Object doConversion(Object obj, int depth, State state) {
147179
}
148180
for (Object o : ((Iterable<?>) obj)) {
149181
if (state.elemsLeft <= 0) {
182+
state.listMapTooLarge = true;
150183
break;
151184
}
152185
newList.add(guardedConversion(o, depth + 1, state));
@@ -178,6 +211,7 @@ private static Object doConversion(Object obj, int depth, State state) {
178211
for (Field[] fields : allFields) {
179212
for (Field f : fields) {
180213
if (state.elemsLeft <= 0) {
214+
state.listMapTooLarge = true;
181215
break outer;
182216
}
183217
if (Modifier.isStatic(f.getModifiers())) {
@@ -239,4 +273,12 @@ private static boolean setAccessible(Field field) {
239273
return false;
240274
}
241275
}
276+
277+
private static String checkStringLength(final String str, final State state) {
278+
if (str.length() > MAX_STRING_LENGTH) {
279+
state.stringTooLong = true;
280+
return str.substring(0, MAX_STRING_LENGTH);
281+
}
282+
return str;
283+
}
242284
}

dd-java-agent/appsec/src/main/java/com/datadog/appsec/gateway/GatewayBridge.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ private Flow<Void> onGrpcServerRequestMessage(RequestContext ctx_, Object obj) {
472472
if (subInfo == null || subInfo.isEmpty()) {
473473
return NoopFlow.INSTANCE;
474474
}
475-
Object convObj = ObjectIntrospection.convert(obj);
475+
Object convObj = ObjectIntrospection.convert(obj, ctx);
476476
DataBundle bundle =
477477
new SingletonDataBundle<>(KnownAddresses.GRPC_SERVER_REQUEST_MESSAGE, convObj);
478478
try {
@@ -574,7 +574,7 @@ private Flow<Void> onRequestBodyProcessed(RequestContext ctx_, Object obj) {
574574
}
575575
DataBundle bundle =
576576
new SingletonDataBundle<>(
577-
KnownAddresses.REQUEST_BODY_OBJECT, ObjectIntrospection.convert(obj));
577+
KnownAddresses.REQUEST_BODY_OBJECT, ObjectIntrospection.convert(obj, ctx));
578578
try {
579579
GatewayContext gwCtx = new GatewayContext(false);
580580
return producerService.publishDataEvent(subInfo, ctx, bundle, gwCtx);

0 commit comments

Comments
 (0)