Skip to content

Commit c0bed73

Browse files
authored
Merge branch 'master' into smola/update-system-tests-20240828
2 parents b339a99 + a5af871 commit c0bed73

27 files changed

Lines changed: 720 additions & 52 deletions

File tree

dd-java-agent/agent-ci-visibility/src/main/java/datadog/trace/civisibility/utils/ProcessHierarchyUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ private static boolean isMavenParent() {
3838
}
3939

4040
private static boolean isGradleDaemon() {
41-
return ClassLoader.getSystemClassLoader().getResource("org/gradle/launcher/daemon/") != null;
41+
return ClassLoader.getSystemClassLoader()
42+
.getResource("org/gradle/launcher/daemon/bootstrap/GradleDaemon.class")
43+
!= null
44+
// double-check this is not a Gradle Worker
45+
&& System.getProperties().getProperty("org.gradle.internal.worker.tmpdir") == null;
4246
}
4347

4448
public static long getParentSessionId() {

dd-java-agent/appsec/src/main/java/com/datadog/appsec/powerwaf/PowerWAFModule.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,14 @@ public void onDataAvailable(
477477
} else if ("redirect_request".equals(actionInfo.type)) {
478478
Flow.Action.RequestBlockingAction rba = createRedirectRequestAction(actionInfo);
479479
flow.setAction(rba);
480-
} else if ("generate_stack".equals(actionInfo.type)
481-
&& Config.get().isAppSecStackTraceEnabled()) {
482-
String stackId = (String) actionInfo.parameters.get("stack_id");
483-
StackTraceEvent stackTraceEvent = createExploitStackTraceEvent(stackId);
484-
reqCtx.reportStackTrace(stackTraceEvent);
480+
} else if ("generate_stack".equals(actionInfo.type)) {
481+
if (Config.get().isAppSecStackTraceEnabled()) {
482+
String stackId = (String) actionInfo.parameters.get("stack_id");
483+
StackTraceEvent stackTraceEvent = createExploitStackTraceEvent(stackId);
484+
reqCtx.reportStackTrace(stackTraceEvent);
485+
} else {
486+
log.debug("Ignoring action with type generate_stack (disabled by config)");
487+
}
485488
} else {
486489
log.info("Ignoring action with type {}", actionInfo.type);
487490
}

dd-java-agent/appsec/src/test/groovy/com/datadog/appsec/powerwaf/PowerWAFModuleSpecification.groovy

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ class PowerWAFModuleSpecification extends DDSpecification {
657657

658658
then:
659659
1 * segment.setTagTop('_dd.appsec.waf.version', _ as String)
660-
1 * segment.setTagTop('_dd.appsec.event_rules.loaded', 115)
660+
1 * segment.setTagTop('_dd.appsec.event_rules.loaded', 116)
661661
1 * segment.setTagTop('_dd.appsec.event_rules.error_count', 1)
662662
1 * segment.setTagTop('_dd.appsec.event_rules.errors', { it =~ /\{"[^"]+":\["bad rule"\]\}/})
663663
1 * segment.setTagTop('asm.keep', true)
@@ -777,11 +777,12 @@ class PowerWAFModuleSpecification extends DDSpecification {
777777
setupWithStubConfigService()
778778
AppSecEvent event
779779
StackTraceEvent stackTrace
780-
injectSysConfig('appsec.stacktrace.enabled', 'true')
781780
pwafModule = new PowerWAFModule() // replace the one created too soon
781+
def attackBundle = MapDataBundle.of(KnownAddresses.HEADERS_NO_COOKIES,
782+
new CaseInsensitiveMap<List<String>>(['user-agent': 'Arachni/generate-stacktrace']))
782783

783784
when:
784-
dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, ATTACK_BUNDLE, gwCtx)
785+
dataListener.onDataAvailable(Stub(ChangeableFlow), ctx, attackBundle, gwCtx)
785786
ctx.closeAdditive()
786787

787788
then:
@@ -791,16 +792,16 @@ class PowerWAFModuleSpecification extends DDSpecification {
791792
ctx.reportEvents(_ as Collection<AppSecEvent>) >> { event = it[0].iterator().next() }
792793
ctx.reportStackTrace(_ as StackTraceEvent) >> { stackTrace = it[0] }
793794

794-
event.rule.id == 'ua0-600-12x'
795+
event.rule.id == 'generate-stacktrace-on-scanner'
795796
event.rule.name == 'Arachni'
796797
event.rule.tags == [type: 'security_scanner', category: 'attack_attempt']
797798

798799
event.ruleMatches[0].operator == 'match_regex'
799-
event.ruleMatches[0].operator_value == '^Arachni\\/v'
800+
event.ruleMatches[0].operator_value == '^Arachni\\/generate-stacktrace'
800801
event.ruleMatches[0].parameters[0].address == 'server.request.headers.no_cookies'
801-
event.ruleMatches[0].parameters[0].highlight == ['Arachni/v']
802+
event.ruleMatches[0].parameters[0].highlight == ['Arachni/generate-stacktrace']
802803
event.ruleMatches[0].parameters[0].key_path == ['user-agent']
803-
event.ruleMatches[0].parameters[0].value == 'Arachni/v0'
804+
event.ruleMatches[0].parameters[0].value == 'Arachni/generate-stacktrace'
804805

805806
event.spanId == 777
806807

dd-java-agent/appsec/src/test/resources/test_multi_config.json

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3803,7 +3803,33 @@
38033803
}
38043804
],
38053805
"transformers": [],
3806-
"on_match": ["block", "stack_trace"]
3806+
"on_match": ["block"]
3807+
},
3808+
{
3809+
"id": "generate-stacktrace-on-scanner",
3810+
"name": "Arachni",
3811+
"tags": {
3812+
"type": "security_scanner",
3813+
"category": "attack_attempt"
3814+
},
3815+
"conditions": [
3816+
{
3817+
"parameters": {
3818+
"inputs": [
3819+
{
3820+
"address": "server.request.headers.no_cookies",
3821+
"key_path": [
3822+
"user-agent"
3823+
]
3824+
}
3825+
],
3826+
"regex": "^Arachni\\/generate-stacktrace"
3827+
},
3828+
"operator": "match_regex"
3829+
}
3830+
],
3831+
"transformers": [],
3832+
"on_match": ["stack_trace"]
38073833
},
38083834
{
38093835
"id": "ua0-600-13x",

dd-java-agent/instrumentation/iast-instrumenter/src/main/java/datadog/trace/instrumentation/iastinstrumenter/IastInstrumentation.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,12 @@ public ElementMatcher<TypeDescription> callerType() {
3737

3838
@Override
3939
public boolean isApplicable(final Set<TargetSystem> enabledSystems) {
40-
return enabledSystems.contains(TargetSystem.IAST)
41-
|| (enabledSystems.contains(TargetSystem.APPSEC) && Config.get().isAppSecRaspEnabled());
40+
return enabledSystems.contains(TargetSystem.IAST) || isRaspEnabled();
41+
}
42+
43+
private boolean isRaspEnabled() {
44+
return InstrumenterConfig.get().getAppSecActivation() == ProductActivation.FULLY_ENABLED
45+
&& Config.get().isAppSecRaspEnabled();
4246
}
4347

4448
@Override

dd-java-agent/instrumentation/iast-instrumenter/src/test/groovy/IastInstrumentationForkedTest.groovy

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import datadog.trace.agent.test.AgentTestRunner
2+
import datadog.trace.agent.tooling.InstrumenterModule
23
import datadog.trace.api.Config
4+
import datadog.trace.api.ProductActivation
35
import datadog.trace.api.config.AppSecConfig
46
import datadog.trace.api.config.IastConfig
57
import datadog.trace.instrumentation.iastinstrumenter.IastInstrumentation
@@ -10,24 +12,50 @@ class IastInstrumentationForkedTest extends AgentTestRunner {
1012
@Shared
1113
boolean iastEnabled = false
1214

15+
@Shared
16+
def appSecActivation = ProductActivation.ENABLED_INACTIVE
17+
1318
@Shared
1419
boolean raspEnabled = false
1520

21+
@Shared
22+
boolean applicable = false
23+
1624
@Shared
1725
Set<Class<?>> expectedCallSites = []
1826

27+
Set<InstrumenterModule.TargetSystem> enabledSystems
28+
1929
@Override
2030
protected void configurePreAgent() {
2131
injectSysConfig(IastConfig.IAST_ENABLED, iastEnabled.toString())
2232
injectSysConfig(AppSecConfig.APPSEC_RASP_ENABLED, raspEnabled.toString())
33+
enabledSystems = new HashSet<>()
34+
if (iastEnabled) {
35+
enabledSystems.add(InstrumenterModule.TargetSystem.IAST)
36+
}
37+
if (appSecActivation == ProductActivation.ENABLED_INACTIVE) {
38+
enabledSystems.add(InstrumenterModule.TargetSystem.APPSEC)
39+
} else if (appSecActivation == ProductActivation.FULLY_ENABLED) {
40+
enabledSystems.add(InstrumenterModule.TargetSystem.APPSEC)
41+
injectSysConfig(AppSecConfig.APPSEC_ENABLED, "true")
42+
} else {
43+
injectSysConfig(AppSecConfig.APPSEC_ENABLED, "false")
44+
}
2345
}
2446

2547
void 'test Iast Instrumentation call site supplier'() {
2648
given:
2749
final instrumentation = new IastInstrumentation()
2850

2951
when:
30-
final callSites = instrumentation.callSites().get().toList()
52+
final shouldApply = instrumentation.isApplicable(enabledSystems)
53+
54+
then:
55+
shouldApply == applicable
56+
57+
when:
58+
final callSites = !applicable ? [] : instrumentation.callSites().get().toList()
3159

3260
then:
3361
callSites.size() == expectedCallSites.size()
@@ -47,25 +75,63 @@ class IastForkedTest extends IastInstrumentationForkedTest {
4775

4876
boolean iastEnabled = true
4977

78+
def appSecActivation = ProductActivation.ENABLED_INACTIVE
79+
5080
boolean raspEnabled = false
5181

82+
boolean applicable = true
83+
5284
Set<Class<?>> expectedCallSites = [MockCallSites, MockCallSitesWithTelemetry]
5385
}
5486

55-
class RaspForkedTest extends IastInstrumentationForkedTest {
87+
class AppSecInactiveRaspForkedTest extends IastInstrumentationForkedTest {
5688

5789
boolean iastEnabled = false
5890

91+
def appSecActivation = ProductActivation.ENABLED_INACTIVE
92+
5993
boolean raspEnabled = true
6094

95+
boolean applicable = false
96+
97+
Set<Class<?>> expectedCallSites = []
98+
}
99+
100+
class AppSecDisabledRaspForkedTest extends IastInstrumentationForkedTest {
101+
102+
boolean iastEnabled = false
103+
104+
def appSecActivation = ProductActivation.FULLY_DISABLED
105+
106+
boolean raspEnabled = true
107+
108+
boolean applicable = false
109+
110+
Set<Class<?>> expectedCallSites = []
111+
}
112+
113+
class AppSecEnabledRaspForkedTest extends IastInstrumentationForkedTest {
114+
115+
boolean iastEnabled = false
116+
117+
def appSecActivation = ProductActivation.FULLY_ENABLED
118+
119+
boolean raspEnabled = true
120+
121+
boolean applicable = true
122+
61123
Set<Class<?>> expectedCallSites = [MockRaspCallSites]
62124
}
63125

64126
class AllCallSitesForkedTest extends IastInstrumentationForkedTest {
65127

66128
boolean iastEnabled = true
67129

130+
def appSecActivation = ProductActivation.FULLY_ENABLED
131+
68132
boolean raspEnabled = true
69133

134+
boolean applicable = true
135+
70136
Set<Class<?>> expectedCallSites = [MockCallSites, MockCallSitesWithTelemetry, MockRaspCallSites]
71137
}

dd-java-agent/instrumentation/iast-instrumenter/src/test/groovy/IastInstrumentationTest.groovy

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,11 @@
11
import datadog.trace.agent.test.AgentTestRunner
2-
import datadog.trace.agent.tooling.InstrumenterModule
3-
import datadog.trace.api.config.AppSecConfig
42
import datadog.trace.api.config.IastConfig
53
import datadog.trace.instrumentation.iastinstrumenter.IastHardcodedSecretListener
64
import datadog.trace.instrumentation.iastinstrumenter.IastInstrumentation
75
import net.bytebuddy.description.type.TypeDescription
86

97
class IastInstrumentationTest extends AgentTestRunner {
108

11-
void 'test Iast Instrumentation enablement'() {
12-
given:
13-
injectSysConfig(AppSecConfig.APPSEC_RASP_ENABLED, Boolean.toString(rasp))
14-
final instrumentation = new IastInstrumentation()
15-
16-
when:
17-
final enabled = instrumentation.isEnabled()
18-
final applicable = instrumentation.isApplicable(enabledSystems as Set<InstrumenterModule.TargetSystem>)
19-
20-
then:
21-
enabled
22-
applicable == expected
23-
24-
where:
25-
enabledSystems | rasp | expected
26-
[] | false | false
27-
[InstrumenterModule.TargetSystem.APPSEC] | false | false
28-
[InstrumenterModule.TargetSystem.IAST] | false | true
29-
[InstrumenterModule.TargetSystem.APPSEC] | true | true
30-
[InstrumenterModule.TargetSystem.IAST, InstrumenterModule.TargetSystem.APPSEC] | false | true
31-
[InstrumenterModule.TargetSystem.IAST, InstrumenterModule.TargetSystem.APPSEC] | true | true
32-
}
33-
349
void 'test Iast Instrumentation type matching'() {
3510
given:
3611
final instrumentation = new IastInstrumentation()

dd-smoke-tests/appsec/springboot/src/test/groovy/datadog/smoketest/appsec/SpringBootSmokeTest.groovy

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,9 @@ class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {
295295
}
296296
}
297297
assert trigger != null, 'test trigger not found'
298+
rootSpan.span.metaStruct != null
299+
def stack = rootSpan.span.metaStruct.get('_dd.stack')
300+
assert stack != null, 'stack is not set'
298301
}
299302

300303
void 'rasp blocks on sql injection'() {

dd-smoke-tests/appsec/src/main/groovy/datadog/smoketest/appsec/AbstractAppSecServerSmokeTest.groovy

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ abstract class AbstractAppSecServerSmokeTest extends AbstractServerSmokeTest {
4343
@Shared
4444
protected String[] defaultAppSecProperties = [
4545
"-Ddd.appsec.enabled=${System.getProperty('smoke_test.appsec.enabled') ?: 'true'}",
46-
// TODO: rely on default once its true
47-
"-Ddd.appsec.rasp.enabled=true",
4846
"-Ddd.profiling.enabled=false",
4947
// disable AppSec rate limit
5048
"-Ddd.appsec.trace.rate.limit=-1"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Ignore all project specific gradle directories/files
2+
.gradle
3+
gradle
4+
build
5+
gradlew
6+
gradlew.bat
7+
8+

0 commit comments

Comments
 (0)