Skip to content

Commit

Permalink
Add smoke tests for grpc.server.method
Browse files Browse the repository at this point in the history
  • Loading branch information
manuel-alvarez-alvarez committed May 28, 2024
1 parent 9cc79fe commit 191ce47
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 53 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package datadog.smoketest.appsec

abstract class AbstractSpringBootWithGRPCAppSecTest extends AbstractAppSecServerSmokeTest {

@Override
ProcessBuilder createProcessBuilder() {
String springBootShadowJar = System.getProperty("datadog.smoketest.appsec.springboot-grpc.shadowJar.path")
assert springBootShadowJar != null

List<String> command = [
javaPath(),
*defaultJavaProperties,
*defaultAppSecProperties,
"-jar",
springBootShadowJar,
"--server.port=${httpPort}"
].collect { it as String }

ProcessBuilder processBuilder = new ProcessBuilder(command)
processBuilder.directory(new File(buildDirectory))
}

static final String ROUTE = 'async_annotation_greeting'
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package datadog.smoketest.appsec


import okhttp3.Request
import spock.lang.Shared

class ServerMethodTest extends AbstractSpringBootWithGRPCAppSecTest {

@Shared
String buildDir = new File(System.getProperty("datadog.smoketest.builddir")).absolutePath
@Shared
String customRulesPath = "${buildDir}/appsec_custom_rules.json"

@Override
ProcessBuilder createProcessBuilder() {
// We run this here to ensure it runs before starting the process. Child setupSpec runs after parent setupSpec,
// so it is not a valid location.
appendRules(customRulesPath, [
[
id : '__test_server_method_bock',
name : 'test rule to block on server method',
tags : [
type : 'test',
category : 'test',
confidence: '1',
],
conditions : [
[
parameters: [
inputs: [[address: 'grpc.server.method']],
regex : '^smoketest',
],
operator : 'match_regex',
]
],
transformers: [],
on_match : ['block']
]
])
return super.createProcessBuilder()
}

void 'test grpc.server.method address'() {
setup:
String url = "http://localhost:${httpPort}/${ROUTE}"
def request = new Request.Builder()
.url("${url}?message=${'Hello!'.bytes.encodeBase64()}")
.get().build()

when:
def response = client.newCall(request).execute()

then:
def responseBodyStr = response.body().string()
responseBodyStr != null
responseBodyStr.contains("bye")
response.body().contentType().toString().contains("text/plain")
response.code() == 200

and:
waitForTraceCount(2) == 2
rootSpans.size() == 2
def grpcRootSpan = rootSpans.find { it.triggers }
grpcRootSpan != null
grpcRootSpan.triggers[0]['rule_matches'][0]['parameters']['address'][0] == 'grpc.server.method'
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,9 @@ package datadog.smoketest.appsec

import okhttp3.Request

class SpringBootWithGRPCAppSecTest extends AbstractAppSecServerSmokeTest {
class ServerRequestMessageTest extends AbstractSpringBootWithGRPCAppSecTest {

@Override
ProcessBuilder createProcessBuilder() {
String springBootShadowJar = System.getProperty("datadog.smoketest.appsec.springboot-grpc.shadowJar.path")
assert springBootShadowJar != null

List<String> command = [
javaPath(),
*defaultJavaProperties,
*defaultAppSecProperties,
"-jar",
springBootShadowJar,
"--server.port=${httpPort}"
].collect { it as String }

ProcessBuilder processBuilder = new ProcessBuilder(command)
processBuilder.directory(new File(buildDirectory))
}

static final String ROUTE = 'async_annotation_greeting'

def greeter() {
void 'test grpc.server.request.message address'() {
setup:
String url = "http://localhost:${httpPort}/${ROUTE}"
def request = new Request.Builder()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
package datadog.smoketest.appsec

import datadog.trace.agent.test.utils.ThreadUtils
import groovy.json.JsonGenerator
import groovy.json.JsonSlurper
import okhttp3.MediaType
import okhttp3.Request
import okhttp3.RequestBody
import org.apache.commons.io.IOUtils
import spock.lang.Shared

import java.nio.charset.StandardCharsets
import java.util.jar.JarFile

class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {

@Shared
Expand All @@ -21,33 +15,30 @@ class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {

def prepareCustomRules() {
// Prepare ruleset with additional test rules
final jarFile = new JarFile(shadowJarPath)
final zipEntry = jarFile.getEntry("appsec/default_config.json")
final content = IOUtils.toString(jarFile.getInputStream(zipEntry), StandardCharsets.UTF_8)
final json = new JsonSlurper().parseText(content) as Map<String, Object>
final rules = json.rules as List<Map<String, Object>>
rules.add([
id: '__test_request_body_block',
name: 'test rule to block on request body',
tags: [
type: 'test',
category: 'test',
confidence: '1',
],
conditions: [
appendRules(
customRulesPath,
[
[
parameters: [
inputs: [ [ address: 'server.request.body' ] ],
regex: 'dd-test-request-body-block',
id : '__test_request_body_block',
name : 'test rule to block on request body',
tags : [
type : 'test',
category : 'test',
confidence: '1',
],
conditions : [
[
parameters: [
inputs: [[address: 'server.request.body']],
regex : 'dd-test-request-body-block',
],
operator : 'match_regex',
]
],
operator: 'match_regex',
transformers: [],
on_match : ['block']
]
],
transformers: [],
on_match: [ 'block' ]
])
final gen = new JsonGenerator.Options().build()
IOUtils.write(gen.toJson(json), new FileOutputStream(customRulesPath, false), StandardCharsets.UTF_8)
])
}

@Override
Expand All @@ -62,7 +53,6 @@ class SpringBootSmokeTest extends AbstractAppSecServerSmokeTest {
command.add(javaPath())
command.addAll(defaultJavaProperties)
command.addAll(defaultAppSecProperties)
command.add("-Ddd.appsec.rules=${customRulesPath}" as String)
command.addAll((String[]) ["-jar", springBootShadowJar, "--server.port=${httpPort}"])

ProcessBuilder processBuilder = new ProcessBuilder(command)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import datadog.smoketest.AbstractServerSmokeTest
import datadog.trace.test.agent.decoder.DecodedSpan
import datadog.trace.test.agent.decoder.DecodedTrace
import datadog.trace.test.agent.decoder.Decoder
import groovy.json.JsonGenerator
import groovy.json.JsonSlurper
import org.apache.commons.io.IOUtils
import spock.lang.Shared

import java.nio.charset.StandardCharsets
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue
import java.util.jar.JarFile

abstract class AbstractAppSecServerSmokeTest extends AbstractServerSmokeTest {

Expand Down Expand Up @@ -78,4 +82,23 @@ abstract class AbstractAppSecServerSmokeTest extends AbstractServerSmokeTest {
}
rootSpans.collectMany {it.triggers }.forEach closure
}

/**
* This method fetches default ruleset included in the agent and appends the selected rules, then it points
* the {@code dd.appsec.rules} variable to the new file
*/
void appendRules(final String path, final List<Map<String, Object>> customRules) {
// Prepare a file with the new rules
final jarFile = new JarFile(shadowJarPath)
final zipEntry = jarFile.getEntry("appsec/default_config.json")
final content = IOUtils.toString(jarFile.getInputStream(zipEntry), StandardCharsets.UTF_8)
final json = new JsonSlurper().parseText(content) as Map<String, Object>
final rules = json.rules as List<Map<String, Object>>
rules.addAll(customRules)
final gen = new JsonGenerator.Options().build()
IOUtils.write(gen.toJson(json), new FileOutputStream(path, false), StandardCharsets.UTF_8)

// Add a new property pointing to the new ruleset
defaultAppSecProperties += "-Ddd.appsec.rules=${path}" as String
}
}

0 comments on commit 191ce47

Please sign in to comment.