Add tests to servlet intrumentation to verify that username is set correctly
MODIFY
dd-java-agent/instrumentation/servlet-2/src/test/groovy/JettyServlet2Test.groovy
dd-java-agent/instrumentation/servlet-2/src/test/groovy/JettyServlet2Test.groovy
@@ -5,10 +5,18 @@ import datadog.trace.agent.test.TestUtils
import datadog.trace.api.DDSpanTypes
import datadog.trace.common.writer.ListWriter
import io.opentracing.util.GlobalTracer
+import okhttp3.Credentials
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
+import org.eclipse.jetty.http.HttpHeaders
+import org.eclipse.jetty.http.security.Constraint
+import org.eclipse.jetty.security.ConstraintMapping
+import org.eclipse.jetty.security.ConstraintSecurityHandler
+import org.eclipse.jetty.security.HashLoginService
+import org.eclipse.jetty.security.LoginService
+import org.eclipse.jetty.security.authentication.BasicAuthenticator
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.ServletContextHandler
@@ -34,9 +42,9 @@ class JettyServlet2Test extends AgentTestRunner {
}
})
// Uncomment when debugging:
- .connectTimeout(1, TimeUnit.HOURS)
- .writeTimeout(1, TimeUnit.HOURS)
- .readTimeout(1, TimeUnit.HOURS)
+ // .connectTimeout(1, TimeUnit.HOURS)
+ // .writeTimeout(1, TimeUnit.HOURS)
+ // .readTimeout(1, TimeUnit.HOURS)
.build()
private Server jettyServer
@@ -55,7 +63,11 @@ class JettyServlet2Test extends AgentTestRunner {
jettyServer = new Server(PORT)
servletContext = new ServletContextHandler()
+ ConstraintSecurityHandler security = setupAuthentication(jettyServer)
+
+ servletContext.setSecurityHandler(security)
servletContext.addServlet(TestServlet2.Sync, "/sync")
+ servletContext.addServlet(TestServlet2.Sync, "/auth/sync")
jettyServer.setHandler(servletContext)
jettyServer.start()
@@ -82,11 +94,13 @@ class JettyServlet2Test extends AgentTestRunner {
def "test #path servlet call"() {
setup:
- def request = new Request.Builder()
+ def requestBuilder = new Request.Builder()
.url("http://localhost:$PORT/$path")
.get()
- .build()
- def response = client.newCall(request).execute()
+ if (auth) {
+ requestBuilder.header(HttpHeaders.AUTHORIZATION, Credentials.basic("user", "password"))
+ }
+ def response = client.newCall(requestBuilder.build()).execute()
expect:
response.body().string().trim() == expectedResponse
@@ -107,6 +121,9 @@ class JettyServlet2Test extends AgentTestRunner {
"component" "java-web-servlet"
"span.type" DDSpanTypes.WEB_SERVLET
"servlet.context" ""
+ if (auth) {
+ "user.principal" "user"
+ }
defaultTags()
}
}
@@ -114,8 +131,9 @@ class JettyServlet2Test extends AgentTestRunner {
}
where:
- path | expectedResponse
- "sync" | "Hello Sync"
+ path | expectedResponse | auth
+ "sync" | "Hello Sync" | false
+ "auth/sync" | "Hello Sync" | true
}
def "test #path error servlet call"() {
@@ -195,4 +213,37 @@ class JettyServlet2Test extends AgentTestRunner {
path | expectedResponse
"sync" | "Hello Sync"
}
+
+ /**
+ * Setup simple authentication for tests
+ * <p>
+ * requests to {@code /auth/*} need login 'user' and password 'password'
+ * <p>
+ * For details @see <a href="http://www.eclipse.org/jetty/documentation/9.3.x/embedded-examples.html">http://www.eclipse.org/jetty/documentation/9.3.x/embedded-examples.html</a>
+ *
+ * @param jettyServer server to attach login service
+ * @return SecurityHandler that can be assigned to servlet
+ */
+ private ConstraintSecurityHandler setupAuthentication(Server jettyServer) {
+ ConstraintSecurityHandler security = new ConstraintSecurityHandler()
+
+ Constraint constraint = new Constraint()
+ constraint.setName("auth")
+ constraint.setAuthenticate(true)
+ constraint.setRoles("role")
+
+ ConstraintMapping mapping = new ConstraintMapping()
+ mapping.setPathSpec("/auth/*")
+ mapping.setConstraint(constraint)
+
+ security.setConstraintMappings(mapping)
+ security.setAuthenticator(new BasicAuthenticator())
+
+ LoginService loginService = new HashLoginService("TestRealm",
+ "src/test/resources/realm.properties")
+ security.setLoginService(loginService)
+ jettyServer.addBean(loginService)
+
+ security
+ }
}

ADD
dd-java-agent/instrumentation/servlet-2/src/test/resources/realm.properties
+user: password,role

MODIFY
dd-java-agent/instrumentation/servlet-3/src/test/groovy/JettyServlet3Test.groovy
dd-java-agent/instrumentation/servlet-3/src/test/groovy/JettyServlet3Test.groovy
@@ -5,12 +5,20 @@ import datadog.trace.agent.test.TestUtils
import datadog.trace.api.DDSpanTypes
import datadog.trace.common.writer.ListWriter
import io.opentracing.util.GlobalTracer
+import okhttp3.Credentials
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
+import org.eclipse.jetty.http.HttpHeaders
+import org.eclipse.jetty.security.ConstraintMapping
+import org.eclipse.jetty.security.ConstraintSecurityHandler
+import org.eclipse.jetty.security.HashLoginService
+import org.eclipse.jetty.security.LoginService
+import org.eclipse.jetty.security.authentication.BasicAuthenticator
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.ServletContextHandler
+import org.eclipse.jetty.util.security.Constraint
import java.lang.reflect.Field
import java.util.concurrent.CountDownLatch
@@ -56,8 +64,13 @@ class JettyServlet3Test extends AgentTestRunner {
jettyServer = new Server(PORT)
servletContext = new ServletContextHandler()
+ ConstraintSecurityHandler security = setupAuthentication(jettyServer)
+
+ servletContext.setSecurityHandler(security)
servletContext.addServlet(TestServlet3.Sync, "/sync")
+ servletContext.addServlet(TestServlet3.Sync, "/auth/sync")
servletContext.addServlet(TestServlet3.Async, "/async")
+ servletContext.addServlet(TestServlet3.Async, "/auth/async")
jettyServer.setHandler(servletContext)
jettyServer.start()
@@ -84,11 +97,13 @@ class JettyServlet3Test extends AgentTestRunner {
def "test #path servlet call"() {
setup:
- def request = new Request.Builder()
+ def requestBuilder = new Request.Builder()
.url("http://localhost:$PORT/$path")
.get()
- .build()
- def response = client.newCall(request).execute()
+ if (auth) {
+ requestBuilder.header(HttpHeaders.AUTHORIZATION, Credentials.basic("user", "password"))
+ }
+ def response = client.newCall(requestBuilder.build()).execute()
expect:
response.body().string().trim() == expectedResponse
@@ -110,6 +125,9 @@ class JettyServlet3Test extends AgentTestRunner {
"span.type" DDSpanTypes.WEB_SERVLET
"servlet.context" ""
"http.status_code" 200
+ if (auth) {
+ "user.principal" "user"
+ }
defaultTags()
}
}
@@ -117,9 +135,11 @@ class JettyServlet3Test extends AgentTestRunner {
}
where:
- path | expectedResponse
- "async" | "Hello Async"
- "sync" | "Hello Sync"
+ path | expectedResponse | auth
+ "async" | "Hello Async" | false
+ "sync" | "Hello Sync" | false
+ "auth/async" | "Hello Async" | true
+ "auth/sync" | "Hello Sync" | true
}
def "servlet instrumentation clears state after async request"() {
@@ -227,4 +247,37 @@ class JettyServlet3Test extends AgentTestRunner {
path | expectedResponse
"sync" | "Hello Sync"
}
+
+ /**
+ * Setup simple authentication for tests
+ * <p>
+ * requests to {@code /auth/*} need login 'user' and password 'password'
+ * <p>
+ * For details @see <a href="http://www.eclipse.org/jetty/documentation/9.3.x/embedded-examples.html">http://www.eclipse.org/jetty/documentation/9.3.x/embedded-examples.html</a>
+ *
+ * @param jettyServer server to attach login service
+ * @return SecurityHandler that can be assigned to servlet
+ */
+ private ConstraintSecurityHandler setupAuthentication(Server jettyServer) {
+ ConstraintSecurityHandler security = new ConstraintSecurityHandler()
+
+ Constraint constraint = new Constraint()
+ constraint.setName("auth")
+ constraint.setAuthenticate(true)
+ constraint.setRoles("role")
+
+ ConstraintMapping mapping = new ConstraintMapping()
+ mapping.setPathSpec("/auth/*")
+ mapping.setConstraint(constraint)
+
+ security.setConstraintMappings(mapping)
+ security.setAuthenticator(new BasicAuthenticator())
+
+ LoginService loginService = new HashLoginService("TestRealm",
+ "src/test/resources/realm.properties")
+ security.setLoginService(loginService)
+ jettyServer.addBean(loginService)
+
+ security
+ }
}

ADD
dd-java-agent/instrumentation/servlet-3/src/test/resources/realm.properties
+user: password,role

Add tests to servlet intrumentation to verify that username is set correctly