Skip to content

Commit c1695f4

Browse files
committed
WIP
1 parent 63ce8fb commit c1695f4

File tree

6 files changed

+119
-0
lines changed

6 files changed

+119
-0
lines changed

dd-java-agent/instrumentation/resteasy-appsec/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ dependencies {
4040
exclude group: 'org.eclipse.jetty', module: 'jetty-server'
4141
}
4242

43+
testFixturesImplementation project(':dd-java-agent:instrumentation:jax-rs-annotations-2')
44+
4345
nettyTestImplementation group: 'io.netty', name: 'netty', version: '3.8.0.Final' // upgrade netty to a version we support
4446
nettyTestImplementation group: 'org.jboss.resteasy', name: 'resteasy-netty', version :'3.0.0.Final'
4547
nettyTestImplementation project(':dd-java-agent:instrumentation:netty-3.8')

dd-smoke-tests/resteasy/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ dependencies {
1616
implementation group: 'org.jboss.resteasy', name: 'resteasy-undertow', version:'3.1.0.Final'
1717
implementation group: 'org.jboss.resteasy', name: 'resteasy-cdi', version:'3.1.0.Final'
1818
implementation group: 'org.jboss.weld.servlet', name: 'weld-servlet', version: '2.4.8.Final'
19+
implementation 'org.jboss.resteasy:resteasy-jackson2-provider:3.1.0.Final'
1920

2021
implementation group: 'javax.el', name: 'javax.el-api', version:'3.0.0'
2122

@@ -24,6 +25,7 @@ dependencies {
2425

2526
testImplementation project(':dd-smoke-tests')
2627
testImplementation(testFixtures(project(":dd-smoke-tests:iast-util")))
28+
testImplementation project(':dd-smoke-tests:appsec')
2729
}
2830

2931
tasks.withType(Test).configureEach {

dd-smoke-tests/resteasy/src/main/java/smoketest/resteasy/App.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package smoketest.resteasy;
22

3+
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
34
import java.util.HashSet;
45
import java.util.Set;
56
import javax.ws.rs.core.Application;
@@ -10,6 +11,8 @@ public class App extends Application {
1011

1112
public App() {
1213
singletons.add(new Resource());
14+
singletons.add(new org.jboss.resteasy.plugins.providers.StringTextStar()); // Writer for String
15+
singletons.add(new JacksonJsonProvider()); // Writer for json
1316
}
1417

1518
@Override

dd-smoke-tests/resteasy/src/main/java/smoketest/resteasy/Resource.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,18 @@ public Response responseLocation(@QueryParam("param") String param) throws URISy
9494
public Response getCookie() throws SQLException {
9595
return Response.ok().cookie(new NewCookie("user-id", "7")).build();
9696
}
97+
98+
@Path("/api_security/response")
99+
@GET
100+
@Produces(MediaType.APPLICATION_JSON)
101+
public Response bodyJson() {
102+
TestEntity testEntity = new TestEntity("testing", "test");
103+
return Response.ok().entity(testEntity).build();
104+
}
105+
106+
@GET
107+
@Path("/api_security/sampling/{i}")
108+
public Response apiSecuritySamplingWithStatus(@PathParam("i") int i) {
109+
return Response.status(i).header("content-type", "text/plain").entity("Hello!\n").build();
110+
}
97111
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package smoketest.resteasy;
2+
3+
public class TestEntity {
4+
public String param1;
5+
public String param2;
6+
7+
public TestEntity() {
8+
super();
9+
}
10+
11+
public TestEntity(String param1, String param2) {
12+
this.param1 = param1;
13+
this.param2 = param2;
14+
}
15+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package smoketest
2+
3+
import datadog.smoketest.appsec.AbstractAppSecServerSmokeTest
4+
import datadog.trace.api.Platform
5+
import okhttp3.Request
6+
import okhttp3.Response
7+
import spock.lang.IgnoreIf
8+
9+
@IgnoreIf({
10+
System.getProperty("java.vendor").contains("IBM") && System.getProperty("java.version").contains("1.8.")
11+
})
12+
class ResteasyAppsecSmokeTest extends AbstractAppSecServerSmokeTest {
13+
14+
@Override
15+
ProcessBuilder createProcessBuilder() {
16+
String jarPath = System.getProperty("datadog.smoketest.resteasy.jar.path")
17+
18+
List<String> command = new ArrayList<>()
19+
command.add(javaPath())
20+
command.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005")
21+
command.addAll(defaultJavaProperties)
22+
command.addAll(defaultAppSecProperties)
23+
if (Platform.isJavaVersionAtLeast(17)) {
24+
command.addAll(["--add-opens", "java.base/java.lang=ALL-UNNAMED"])
25+
}
26+
command.addAll(["-jar", jarPath, Integer.toString(httpPort)])
27+
ProcessBuilder processBuilder = new ProcessBuilder(command)
28+
processBuilder.directory(new File(buildDirectory))
29+
}
30+
31+
void 'API Security samples only one request per endpoint'() {
32+
given:
33+
def url = "http://localhost:${httpPort}/hello/api_security/sampling/200?test=value"
34+
def request = new Request.Builder()
35+
.url(url)
36+
.addHeader('X-My-Header', "value")
37+
.get()
38+
.build()
39+
40+
when:
41+
List<Response> responses = (1..3).collect {
42+
client.newCall(request).execute()
43+
}
44+
45+
then:
46+
responses.each {
47+
assert it.code() == 200
48+
}
49+
waitForTraceCount(3)
50+
def spans = rootSpans.toList().toSorted { it.span.duration }
51+
spans.size() == 3
52+
def sampledSpans = spans.findAll {
53+
it.meta.keySet().any {
54+
it.startsWith('_dd.appsec.s.req.')
55+
}
56+
}
57+
sampledSpans.size() == 1
58+
def span = sampledSpans[0]
59+
span.meta.containsKey('_dd.appsec.s.req.query')
60+
span.meta.containsKey('_dd.appsec.s.req.params')
61+
span.meta.containsKey('_dd.appsec.s.req.headers')
62+
}
63+
64+
65+
void 'test response schema extraction'() {
66+
given:
67+
def url = "http://localhost:${httpPort}/hello/api_security/response"
68+
def request = new Request.Builder()
69+
.url(url)
70+
.get()
71+
.build()
72+
73+
when:
74+
final response = client.newCall(request).execute()
75+
waitForTraceCount(1)
76+
77+
then:
78+
response.code() == 200
79+
def span = rootSpans.first()
80+
span.meta.containsKey('_dd.appsec.s.res.headers')
81+
span.meta.containsKey('_dd.appsec.s.res.body')
82+
}
83+
}

0 commit comments

Comments
 (0)