Skip to content

Commit 1464796

Browse files
Fix more system-tests
1 parent 82417c0 commit 1464796

File tree

4 files changed

+64
-37
lines changed

4 files changed

+64
-37
lines changed

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

+20-4
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import datadog.trace.api.gateway.SubscriptionService;
3737
import datadog.trace.api.http.StoredBodySupplier;
3838
import datadog.trace.api.internal.TraceSegment;
39+
import datadog.trace.api.telemetry.LoginEvent;
3940
import datadog.trace.api.telemetry.RuleType;
4041
import datadog.trace.api.telemetry.WafMetricCollector;
4142
import datadog.trace.bootstrap.instrumentation.api.Tags;
@@ -83,6 +84,14 @@ public class GatewayBridge {
8384
"appsec.events.users.login.success.track", "appsec.events.users.login.failure.track"
8485
};
8586

87+
private static final Map<String, LoginEvent> EVENT_MAPPINGS = new HashMap<>();
88+
89+
static {
90+
EVENT_MAPPINGS.put("users.login.success", LoginEvent.LOGIN_SUCCESS);
91+
EVENT_MAPPINGS.put("users.login.failure", LoginEvent.LOGIN_FAILURE);
92+
EVENT_MAPPINGS.put("users.signup", LoginEvent.SIGN_UP);
93+
}
94+
8695
private static final String METASTRUCT_EXPLOIT = "exploit";
8796

8897
private final SubscriptionService subscriptionService;
@@ -264,18 +273,25 @@ private Flow<Void> onLoginEvent(
264273
return NoopFlow.INSTANCE;
265274
}
266275

276+
// parse the event (might be null for custom events sent via the SDK)
277+
final LoginEvent sourceEvent = EVENT_MAPPINGS.get(eventName);
278+
267279
// skip event if we have an SDK one
268280
if (mode != SDK) {
269281
segment.setTagTop("_dd.appsec.usr.login", user);
270-
segment.setTagTop("_dd.appsec.usr.id", user);
271282
if (ctx.getUserLoginSource() == SDK) {
272283
return NoopFlow.INSTANCE;
273284
}
285+
} else {
286+
if (sourceEvent == LoginEvent.LOGIN_SUCCESS) {
287+
segment.setTagTop("usr.id", user, false);
288+
} else {
289+
segment.setTagTop("appsec.events." + eventName + ".usr.id", user, true);
290+
}
274291
}
275292

276293
// update user span tags
277294
segment.setTagTop("appsec.events." + eventName + ".usr.login", user, true);
278-
segment.setTagTop("appsec.events." + eventName + ".usr.id", user, true);
279295

280296
// update current context with new user login
281297
ctx.setUserLoginSource(mode);
@@ -289,9 +305,9 @@ private Flow<Void> onLoginEvent(
289305
final List<Address<?>> addresses = new ArrayList<>(3);
290306
addresses.add(KnownAddresses.USER_LOGIN);
291307
addresses.add(KnownAddresses.USER_ID);
292-
if (eventName.endsWith("login.success")) {
308+
if (sourceEvent == LoginEvent.LOGIN_SUCCESS) {
293309
addresses.add(KnownAddresses.LOGIN_SUCCESS);
294-
} else if (eventName.endsWith("login.failure")) {
310+
} else if (sourceEvent == LoginEvent.LOGIN_FAILURE) {
295311
addresses.add(KnownAddresses.LOGIN_FAILURE);
296312
}
297313
final MapDataBundle.Builder bundleBuilder =

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/gateway/GatewayBridgeSpecification.groovy

+29-28
Original file line numberDiff line numberDiff line change
@@ -141,10 +141,10 @@ class GatewayBridgeSpecification extends DDSpecification {
141141
void 'request_end closes context reports attacks and publishes event'() {
142142
AppSecEvent event = Mock()
143143
AppSecRequestContext mockAppSecCtx = Mock(AppSecRequestContext)
144-
mockAppSecCtx.requestHeaders >> ['accept':['header_value']]
144+
mockAppSecCtx.requestHeaders >> ['accept': ['header_value']]
145145
mockAppSecCtx.responseHeaders >> [
146-
'some-header': ['123'],
147-
'content-type':['text/html; charset=UTF-8']]
146+
'some-header' : ['123'],
147+
'content-type': ['text/html; charset=UTF-8']]
148148
RequestContext mockCtx = Stub(RequestContext) {
149149
getData(RequestContextSlot.APPSEC) >> mockAppSecCtx
150150
getTraceSegment() >> traceSegment
@@ -155,7 +155,7 @@ class GatewayBridgeSpecification extends DDSpecification {
155155
def flow = requestEndedCB.apply(mockCtx, spanInfo)
156156

157157
then:
158-
1 * spanInfo.getTags() >> ['http.client_ip':'1.1.1.1']
158+
1 * spanInfo.getTags() >> ['http.client_ip': '1.1.1.1']
159159
1 * mockAppSecCtx.transferCollectedEvents() >> [event]
160160
1 * mockAppSecCtx.peerAddress >> '2001::1'
161161
1 * mockAppSecCtx.close(false)
@@ -175,7 +175,7 @@ class GatewayBridgeSpecification extends DDSpecification {
175175
AppSecRequestContext mockAppSecCtx = Mock(AppSecRequestContext)
176176
mockAppSecCtx.requestHeaders >> [
177177
'x-real-ip': ['10.0.0.1'],
178-
forwarded: ['for=127.0.0.1', 'for="[::1]", for=8.8.8.8'],
178+
forwarded : ['for=127.0.0.1', 'for="[::1]", for=8.8.8.8'],
179179
]
180180
RequestContext mockCtx = Stub(RequestContext) {
181181
getData(RequestContextSlot.APPSEC) >> mockAppSecCtx
@@ -188,7 +188,7 @@ class GatewayBridgeSpecification extends DDSpecification {
188188

189189
then:
190190
1 * mockAppSecCtx.transferCollectedEvents() >> [Stub(AppSecEvent)]
191-
1 * spanInfo.getTags() >> ['http.client_ip':'8.8.8.8']
191+
1 * spanInfo.getTags() >> ['http.client_ip': '8.8.8.8']
192192
1 * traceSegment.setTagTop('actor.ip', '8.8.8.8')
193193
}
194194

@@ -607,7 +607,7 @@ class GatewayBridgeSpecification extends DDSpecification {
607607
Object obj = 'hello'
608608

609609
setup:
610-
eventDispatcher.getDataSubscribers({KnownAddresses.REQUEST_BODY_OBJECT in it}) >> nonEmptyDsInfo
610+
eventDispatcher.getDataSubscribers({ KnownAddresses.REQUEST_BODY_OBJECT in it }) >> nonEmptyDsInfo
611611
eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext)
612612
>> { bundle = it[2]; gatewayContext = it[3]; NoopFlow.INSTANCE }
613613

@@ -951,18 +951,18 @@ class GatewayBridgeSpecification extends DDSpecification {
951951
void 'default request headers are always set when appsec is enabled'() {
952952
final mockAppSecCtx = Mock(AppSecRequestContext)
953953
mockAppSecCtx.requestHeaders >> [
954-
'host': ['localhost'],
955-
'accept': ['text/plain'],
956-
'content-type': ['application/json'],
957-
'user-agent': ['mozilla'],
958-
'x-amzn-trace-id': ['Root=1-65ae48bc-04fb551979979b6c57973027'],
954+
'host' : ['localhost'],
955+
'accept' : ['text/plain'],
956+
'content-type' : ['application/json'],
957+
'user-agent' : ['mozilla'],
958+
'x-amzn-trace-id' : ['Root=1-65ae48bc-04fb551979979b6c57973027'],
959959
'cloudfront-viewer-ja3-fingerprint': ['e7d705a3286e19ea42f587b344ee6865'],
960-
'cf-ray': ['230b030023ae2822-SJC'],
961-
'x-cloud-trace-context': ['105445aa7843bc8bf206b12000100000/1'],
962-
'x-appgw-trace-id': ['ac882cd65a2712a0fe1289ec2bb6aee7'],
963-
'x-sigsci-requestid': ['55c24b96ca84c02201000001'],
964-
'x-sigsci-tags': ['SQLI, XSS'],
965-
'akamai-user-risk': ['uuid=913c4545-757b-4d8d-859d-e1361a828361;status=0'],
960+
'cf-ray' : ['230b030023ae2822-SJC'],
961+
'x-cloud-trace-context' : ['105445aa7843bc8bf206b12000100000/1'],
962+
'x-appgw-trace-id' : ['ac882cd65a2712a0fe1289ec2bb6aee7'],
963+
'x-sigsci-requestid' : ['55c24b96ca84c02201000001'],
964+
'x-sigsci-tags' : ['SQLI, XSS'],
965+
'akamai-user-risk' : ['uuid=913c4545-757b-4d8d-859d-e1361a828361;status=0'],
966966
]
967967
final mockCtx = Stub(RequestContext) {
968968
getData(RequestContextSlot.APPSEC) >> mockAppSecCtx
@@ -1099,12 +1099,11 @@ class GatewayBridgeSpecification extends DDSpecification {
10991099
0 * _
11001100
} else {
11011101
1 * traceSegment.setTagTop('appsec.events.users.signup.usr.login', expectedUser, true)
1102-
1 * traceSegment.setTagTop('appsec.events.users.signup.usr.id', expectedUser, true)
11031102
if (mode != SDK) {
11041103
1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUser)
1105-
1 * traceSegment.setTagTop('_dd.appsec.usr.id', expectedUser)
11061104
1 * traceSegment.setTagTop('_dd.appsec.events.users.signup.auto.mode', mode.fullName(), true)
11071105
} else {
1106+
1 * traceSegment.setTagTop('appsec.events.users.signup.usr.id', expectedUser, true)
11081107
1 * traceSegment.setTagTop('_dd.appsec.events.users.signup.sdk', true, true)
11091108
}
11101109
1 * traceSegment.setTagTop('appsec.events.users.signup.track', true, true)
@@ -1137,12 +1136,11 @@ class GatewayBridgeSpecification extends DDSpecification {
11371136
0 * _
11381137
} else {
11391138
1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', expectedUser, true)
1140-
1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.id', expectedUser, true)
11411139
if (mode != SDK) {
11421140
1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUser)
1143-
1 * traceSegment.setTagTop('_dd.appsec.usr.id', expectedUser)
11441141
1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', mode.fullName(), true)
11451142
} else {
1143+
1 * traceSegment.setTagTop('usr.id', expectedUser, false)
11461144
1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', true, true)
11471145
}
11481146
1 * traceSegment.setTagTop('appsec.events.users.login.success.track', true, true)
@@ -1176,12 +1174,11 @@ class GatewayBridgeSpecification extends DDSpecification {
11761174
0 * _
11771175
} else {
11781176
1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.login', expectedUser, true)
1179-
1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.id', expectedUser, true)
11801177
if (mode != SDK) {
11811178
1 * traceSegment.setTagTop('_dd.appsec.usr.login', expectedUser)
1182-
1 * traceSegment.setTagTop('_dd.appsec.usr.id', expectedUser)
11831179
1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.auto.mode', mode.fullName(), true)
11841180
} else {
1181+
1 * traceSegment.setTagTop('appsec.events.users.login.failure.usr.id', expectedUser, true)
11851182
1 * traceSegment.setTagTop('_dd.appsec.events.users.login.failure.sdk', true, true)
11861183
}
11871184
1 * traceSegment.setTagTop('appsec.events.users.login.failure.track', true, true)
@@ -1255,21 +1252,25 @@ class GatewayBridgeSpecification extends DDSpecification {
12551252
12561253
then:
12571254
1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', firstUser, true)
1258-
1 * traceSegment.setTagTop('appsec.events.users.login.success.usr.id', firstUser, true)
1255+
1 * traceSegment.setTagTop('usr.id', firstUser, false)
1256+
1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', true, true)
1257+
12591258
0 * traceSegment.setTagTop('_dd.appsec.usr.login', _)
1260-
0 * traceSegment.setTagTop('_dd.appsec.usr.id', _)
12611259
0 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', _, _)
1260+
12621261
1 * eventDispatcher.publishDataEvent(nonEmptyDsInfo, ctx.data, _ as DataBundle, _ as GatewayContext) >> NoopFlow.INSTANCE
12631262
12641263
when:
12651264
loginEventCB.apply(ctx, IDENTIFICATION, 'users.login.success', null, secondUser, null)
12661265
12671266
then:
12681267
0 * traceSegment.setTagTop('appsec.events.users.login.success.usr.login', _, _)
1269-
0 * traceSegment.setTagTop('appsec.events.users.login.success.usr.id', _, _)
1268+
0 * traceSegment.setTagTop('usr.id', _, _)
1269+
0 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.sdk', _, _)
1270+
12701271
1 * traceSegment.setTagTop('_dd.appsec.usr.login', secondUser)
1271-
1 * traceSegment.setTagTop('_dd.appsec.usr.id', secondUser)
12721272
1 * traceSegment.setTagTop('_dd.appsec.events.users.login.success.auto.mode', IDENTIFICATION.fullName(), true)
1273+
12731274
0 * eventDispatcher.publishDataEvent
12741275
}
12751276
}

internal-api/src/main/java/datadog/trace/api/telemetry/WafMetricCollector.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public void missingUserLogin(final LoginFramework framework, final LoginEvent ev
109109
}
110110

111111
public void missingUserId(final LoginFramework framework) {
112-
missingUserLoginQueue.incrementAndGet(framework.ordinal());
112+
missingUserIdQueue.incrementAndGet(framework.ordinal());
113113
}
114114

115115
@Override
@@ -215,7 +215,7 @@ public void prepareMetrics() {
215215
}
216216
}
217217

218-
// Missing user id
218+
// Missing user login
219219
for (LoginFramework framework : LoginFramework.values()) {
220220
for (LoginEvent event : LoginEvent.values()) {
221221
final int ordinal = framework.ordinal() * LoginEvent.getNumValues() + event.ordinal();
@@ -228,6 +228,16 @@ public void prepareMetrics() {
228228
}
229229
}
230230
}
231+
232+
// Missing user id
233+
for (LoginFramework framework : LoginFramework.values()) {
234+
long counter = missingUserIdQueue.getAndSet(framework.ordinal(), 0);
235+
if (counter > 0) {
236+
if (!rawMetricsQueue.offer(new MissingUserIdMetric(counter, framework.getTag()))) {
237+
return;
238+
}
239+
}
240+
}
231241
}
232242

233243
public abstract static class WafMetric extends MetricCollector.Metric {

internal-api/src/test/groovy/datadog/trace/api/telemetry/WafMetricCollectorTest.groovy

+3-3
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,13 @@ class WafMetricCollectorTest extends DDSpecification {
238238
}
239239
assert tags["framework"] == LoginFramework.SPRING_SECURITY.getTag()
240240
switch (tags["event_type"]) {
241-
case LoginEvent.LOGIN_SUCCESS.getTelemetryTag():
241+
case LoginEvent.LOGIN_SUCCESS.getTag():
242242
assert metric.value == loginSuccessCount
243243
break
244-
case LoginEvent.LOGIN_FAILURE.getTelemetryTag():
244+
case LoginEvent.LOGIN_FAILURE.getTag():
245245
assert metric.value == loginFailureCount
246246
break
247-
case LoginEvent.SIGN_UP.getTelemetryTag():
247+
case LoginEvent.SIGN_UP.getTag():
248248
assert metric.value == signupCount
249249
break
250250
default:

0 commit comments

Comments
 (0)