Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AppSec Xml support for play 2.6 #6100

Merged
merged 1 commit into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import play.routing.Router
import play.routing.RoutingDsl
import scala.collection.JavaConverters
import scala.concurrent.ExecutionContextExecutor
import scala.xml.NodeSeq

import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionStage
Expand All @@ -26,6 +27,7 @@ import java.util.function.Supplier
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_JSON
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_MULTIPART
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_URLENCODED
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_XML
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.CREATED
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.CUSTOM_EXCEPTION
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.ERROR
Expand Down Expand Up @@ -151,6 +153,13 @@ class PlayRouters {
Results.status(BODY_JSON.status, Json$.MODULE$.stringify(json))
}
} as Supplier)
.POST(BODY_XML.path).routeTo({
->
controller(BODY_XML) {
NodeSeq node = body().asXml().get()
Results.status(BODY_XML.status, node.toString())
}
} as Supplier)
.build()
}

Expand Down Expand Up @@ -281,6 +290,16 @@ class PlayRouters {
}
}, execContext)
} as Supplier)
.POST(BODY_XML.path).routeAsync({
->
NodeSeq node = body().asXml().get()
CompletableFuture.supplyAsync({
->
controller(BODY_XML) {
Results.status(BODY_XML.status, node.toString())
}
}, execContext)
} as Supplier)
.build()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ import datadog.trace.api.DDTags
import datadog.trace.bootstrap.instrumentation.api.Tags
import datadog.trace.instrumentation.play26.PlayHttpServerDecorator
import groovy.transform.CompileStatic
import okhttp3.MediaType
import okhttp3.RequestBody
import play.server.Server

import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_XML
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.CUSTOM_EXCEPTION
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.EXCEPTION
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.FORWARDED
Expand Down Expand Up @@ -142,4 +145,29 @@ class PlayServerTest extends HttpServerTest<Server> {
}
}
}

def 'test instrumentation gateway xml request body'() {
setup:
def request = request(
BODY_XML, 'POST',
RequestBody.create(MediaType.get('text/xml'), '<foo attr="attr_value">mytext<bar></bar></foo>'))
.build()
def response = client.newCall(request).execute()
if (isDataStreamsEnabled()) {
TEST_DATA_STREAMS_WRITER.waitForGroups(1)
}
String body = response.body().charStream().text


expect:
body == BODY_XML.body || body == '<?xml version="1.0" encoding="UTF-8"?><foo attr="attr_value">mytext<bar/></foo>'

when:
TEST_WRITER.waitForTraces(1)

then:
TEST_WRITER.get(0).any {
it.getTag('request.body.converted') == '[[children:[mytext, [:]], attributes:[attr:attr_value]]]'
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import datadog.appsec.api.blocking.Blocking
import datadog.trace.agent.test.base.HttpServerTest
import datadog.trace.instrumentation.play26.server.TestHttpErrorHandler
import groovy.transform.CompileStatic
import org.w3c.dom.Document
import play.BuiltInComponents
import play.libs.concurrent.ClassLoaderExecution
import play.mvc.Http
Expand All @@ -16,13 +17,18 @@ import play.routing.Router
import play.routing.RoutingDsl
import scala.concurrent.ExecutionContextExecutor

import javax.xml.transform.OutputKeys
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionStage
import java.util.concurrent.ExecutorService

import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_JSON
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_MULTIPART
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_URLENCODED
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.BODY_XML
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.CREATED
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.CUSTOM_EXCEPTION
import static datadog.trace.agent.test.base.HttpServerTest.ServerEndpoint.ERROR
Expand Down Expand Up @@ -118,6 +124,12 @@ class PlayRouters {
Results.status(BODY_JSON.status, new ObjectMapper().writeValueAsString(json))
}
} as RequestFunctions.Params0<Result>)
.POST(BODY_XML.path).routingTo({ Http.Request req ->
controller(BODY_XML) {
Document xml = req.body().asXml()
Results.status(BODY_XML.status, documentToString(xml))
}
} as RequestFunctions.Params0<Result>)
.build()
}

Expand Down Expand Up @@ -246,6 +258,15 @@ class PlayRouters {
}
}, execContext)
} as RequestFunctions.Params0<? extends CompletionStage<Result>>)
.POST(BODY_XML.path).routingAsync({ Http.Request req ->
Document xml = req.body().asXml()
CompletableFuture.supplyAsync({
->
controller(BODY_XML) {
Results.status(BODY_XML.status, documentToString(xml))
}
}, execContext)
} as RequestFunctions.Params0<? extends CompletionStage<Result>>)
.build()
}

Expand All @@ -263,4 +284,13 @@ class PlayRouters {
})
}
}

private static String documentToString(Document doc) {
StringWriter writer = new StringWriter()
TransformerFactory.newInstance().newTransformer().with {
setOutputProperty(OutputKeys.INDENT, "no")
transform(new DOMSource(doc), new StreamResult(writer))
}
writer.toString()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ POST /created datadog.trace.instrumentation.play26.server.
POST /body-urlencoded datadog.trace.instrumentation.play26.server.latestdep.PlayController.bodyUrlencoded()
POST /body-multipart datadog.trace.instrumentation.play26.server.latestdep.PlayController.bodyMultipart()
POST /body-json datadog.trace.instrumentation.play26.server.latestdep.PlayController.bodyJson()
POST /body-xml datadog.trace.instrumentation.play26.server.latestdep.PlayController.bodyXml()
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package datadog.trace.instrumentation.play26.server.latestdep

import scala.collection.Seq

object ImplicitConversions {
implicit class MapExtensions[A](m: Iterable[(String, A)]) {
def toStringAsGroovy: String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import play.api.libs.json.{JsNull, JsValue, Json}
import play.api.mvc._

import scala.concurrent.{ExecutionContext, Future}
import scala.xml.NodeSeq

class PlayController(cc: ControllerComponents)(implicit ec: ExecutionContext) extends AbstractController(cc) {
def success() = controller(ServerEndpoint.SUCCESS) { _ =>
Expand Down Expand Up @@ -81,6 +82,11 @@ class PlayController(cc: ControllerComponents)(implicit ec: ExecutionContext) ex
Results.Ok(Json.stringify(body))
}

def bodyXml = controller(ServerEndpoint.BODY_XML) { request =>
val body : NodeSeq = request.body.asXml.getOrElse(NodeSeq.Empty)
Results.Ok(body.toString())
}

private def controller(endpoint: ServerEndpoint)(block: Request[AnyContent] => Result) : Action[AnyContent] = {
Action.async { request =>
Future {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import play.api.routing.sird._

import java.util.concurrent.ExecutorService
import scala.concurrent.{ExecutionContext, Future}
import scala.xml.NodeSeq

object PlayRoutersScala {

Expand Down Expand Up @@ -149,6 +150,13 @@ object PlayRoutersScala {
Results.Ok(Json.stringify(body))
}
}

case POST(p"/body-xml") => defaultActionBuilder.async(parser) { request =>
controller(BODY_XML) {
val body: NodeSeq = request.body.asXml.getOrElse(NodeSeq.Empty)
Results.Ok(body.toString())
}
}
}
}

Expand Down
Loading
Loading