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

Add standalone ASM billing support #7040

Merged
merged 62 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
2076f6f
add new config property
jandro996 May 9, 2024
6ec447f
Add _dd.apm.enabled:0 tag
jandro996 May 13, 2024
ecdd731
Add _dd.apm.enabled:0 tag
jandro996 May 13, 2024
7bb2586
Disabling the computation agent-side of the APM trace metrics by pret…
jandro996 May 13, 2024
8c752a3
Disabling the computation library-side of the APM trace metrics
jandro996 May 14, 2024
e1efe75
refactor config to have a property that determines if tracing is need…
jandro996 May 16, 2024
07af6b8
tracing libraries must configure the tracer sampling mechanism so tha…
jandro996 May 21, 2024
31f75b0
tracing libraries must configure the tracer sampling mechanism so tha…
jandro996 May 21, 2024
cd5e0be
fix merge issue
jandro996 May 21, 2024
d750c8a
Add test to areTracingDependantProductsEnabled
jandro996 May 21, 2024
6c89550
rollback
jandro996 May 21, 2024
ec850f2
Standalone ASM, disabling APM tracing and its billing, must be enable…
jandro996 May 21, 2024
993c708
Refactor required sampler and add test
jandro996 May 22, 2024
5fb0d2a
Add Sampler test
jandro996 May 22, 2024
87df43d
introduce a new propagated span tag _dd.p.appsec: 1 providing the kno…
jandro996 May 22, 2024
3dfeb58
self code review corrections
jandro996 May 22, 2024
950cf68
Add new appsec ad hoc propagation tag
jandro996 May 30, 2024
03da7bc
move p.appsec from DDtags to Tags
jandro996 May 30, 2024
5ac2827
Add unit test to TagInterceptor
jandro996 May 30, 2024
f991aa1
Add smoke tests
jandro996 May 31, 2024
132eb2f
clean Controller
jandro996 May 31, 2024
082e433
clean test
jandro996 May 31, 2024
687a713
Avoid possible cast exception
jandro996 May 31, 2024
8080ba5
New . smoke test to cover RFC scenarios with the 1st one
jandro996 May 31, 2024
a913cc6
All scenarios implemented
jandro996 Jun 1, 2024
cd9b73f
change Tags.PROPAGATED_APPSEC "1" for true
jandro996 Jun 3, 2024
4eb0112
change Tags.PROPAGATED_APPSEC "1" for true
jandro996 Jun 3, 2024
b7de937
Fix codenarc
jandro996 Jun 3, 2024
38978de
Fix test
jandro996 Jun 3, 2024
3c3b9f5
Add appsec propagation tag to other codecs
jandro996 Jun 4, 2024
340da3c
Rename sampler and modify context to be able to modify the sampling p…
jandro996 Jun 6, 2024
768de96
BE able to stop propagation when standalone is enabled and no appsec …
jandro996 Jun 7, 2024
34f2112
fix test
jandro996 Jun 7, 2024
a7c02dd
fix rebase
jandro996 Jun 7, 2024
c253166
Add stop propagation test
jandro996 Jun 7, 2024
86554b8
spotless
jandro996 Jun 10, 2024
af0fb3c
Update dd-smoke-tests/asm-standalone-billing/src/test/groovy/datadog/…
jandro996 Jun 10, 2024
36cafea
Update dd-smoke-tests/asm-standalone-billing/src/test/groovy/datadog/…
jandro996 Jun 10, 2024
87a6c85
refactor experimentalAppSecStandaloneEnabled
jandro996 Jun 10, 2024
1cc7f6e
clean comments
jandro996 Jun 10, 2024
5b9a04d
change valid values for _dd.p.appsec
jandro996 Jun 10, 2024
4b07571
add new test case
jandro996 Jun 10, 2024
2e2ee21
add _dd. to asux propagation tag
jandro996 Jun 10, 2024
028bedd
move propagation tag set to PowerWaf
jandro996 Jun 10, 2024
b87040b
improve code
jandro996 Jun 10, 2024
abce946
Update dd-trace-core/src/main/java/datadog/trace/common/sampling/AsmS…
jandro996 Jun 10, 2024
efe6140
Update dd-trace-core/src/main/java/datadog/trace/common/sampling/AsmS…
jandro996 Jun 10, 2024
43f5c23
fix spotless
jandro996 Jun 10, 2024
1240d44
Remove not necessary tests
jandro996 Jun 11, 2024
91b9b12
add tests to validate system tests
jandro996 Jun 17, 2024
49c5b75
fix merge
jandro996 Jun 17, 2024
e5afce0
fix codenarc
jandro996 Jun 17, 2024
35b6ef8
remove leftovers
jandro996 Jun 21, 2024
ef4d845
Add appSecStandaloneEnabled to toString
jandro996 Jun 21, 2024
2ea9ff2
minor improvements in PTags codecs and add more tests
jandro996 Jun 24, 2024
4195bf4
Add documented constant to 1 minute value for asm stand alone sampler
jandro996 Jun 24, 2024
eb471eb
cache the TagValue.from("1") value
jandro996 Jun 24, 2024
67c66b6
move Appsec references from DDSpanContext
jandro996 Jun 24, 2024
3cfef89
add test to canAvoidSamplingPriorityLock
jandro996 Jun 24, 2024
26c7ee4
update the config to disable the metric enable flag according standal…
jandro996 Jun 25, 2024
7a8c016
fix test
jandro996 Jun 25, 2024
a88ab8a
increase rate to avoid test flakiness
jandro996 Jun 26, 2024
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 @@ -98,6 +98,7 @@ private VulnerabilityBatch getOrCreateVulnerabilityBatch(final AgentSpan span) {
// TODO: We need to check if we can have an API with more fine-grained semantics on why traces
// are kept.
segment.setTagTop(Tags.ASM_KEEP, true);
segment.setTagTop(Tags.PROPAGATED_APPSEC, true);
jandro996 marked this conversation as resolved.
Show resolved Hide resolved
return batch;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class ReporterTest extends DDSpecification {
]
}''', batch.toString(), true)
1 * traceSegment.setTagTop('asm.keep', true)
1 * traceSegment.setTagTop('_dd.p.appsec', true)
0 * _
}

Expand Down Expand Up @@ -146,6 +147,7 @@ class ReporterTest extends DDSpecification {
]
}''', batch.toString(), true)
1 * traceSegment.setTagTop('asm.keep', true)
1 * traceSegment.setTagTop('_dd.p.appsec', true)
0 * _
}

Expand Down Expand Up @@ -269,6 +271,7 @@ class ReporterTest extends DDSpecification {
1 * traceSegment.getDataTop('iast') >> null
1 * traceSegment.setDataTop('iast', _ as VulnerabilityBatch)
1 * traceSegment.setTagTop('asm.keep', true)
1 * traceSegment.setTagTop('_dd.p.appsec', true)
1 * traceSegment.setTagTop('_dd.iast.enabled', 1)
0 * _
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,10 @@ public void onDataAvailable(
// Keep event related span, because it could be ignored in case of
// reduced datadog sampling rate.
activeSpan.getLocalRootSpan().setTag(Tags.ASM_KEEP, true);
// If APM is disabled, inform downstream services that the current
// distributed trace contains at least one ASM event and must inherit
// the given force-keep priority
activeSpan.getLocalRootSpan().setTag(Tags.PROPAGATED_APPSEC, true);
} else {
// If active span is not available the ASK_KEEP tag will be set in the GatewayBridge
// when the request ends
Expand Down
31 changes: 31 additions & 0 deletions dd-smoke-tests/asm-standalone-billing/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.15'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'java-test-fixtures'
}

apply from: "$rootDir/gradle/java.gradle"
description = 'ASM Standalone Billing Tests.'

java {
sourceCompatibility = '1.8'
}

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'io.opentracing', name: 'opentracing-api', version: '0.32.0'
implementation group: 'io.opentracing', name: 'opentracing-util', version: '0.32.0'
implementation project(':dd-trace-api')
testImplementation project(':dd-smoke-tests')
testImplementation(testFixtures(project(":dd-smoke-tests:iast-util")))
}

tasks.withType(Test).configureEach {
dependsOn "bootJar"
jvmArgs "-Ddatadog.smoketest.springboot.shadowJar.path=${tasks.bootJar.archiveFile.get()}"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package datadog.smoketest.asmstandalonebilling;

import java.util.EnumSet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.SessionTrackingMode;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
@Bean
public ServletContextInitializer servletContextInitializer() {
return new SessionTrackingConfig();
}

private class SessionTrackingConfig implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
EnumSet<SessionTrackingMode> sessionTrackingModes = EnumSet.of(SessionTrackingMode.COOKIE);
servletContext.setSessionTrackingModes(sessionTrackingModes);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package datadog.smoketest.asmstandalonebilling;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import io.opentracing.Span;
import io.opentracing.util.GlobalTracer;
import java.io.IOException;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/rest-api")
public class Controller {

@GetMapping("/greetings")
public String greetings(
@RequestParam(name = "url", required = false) String url,
@RequestParam(name = "forceKeep", required = false) boolean forceKeep) {
if (forceKeep) {
forceKeepSpan();
}
if (url != null) {
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject(url, String.class);
}
return "Hello I'm service " + System.getProperty("dd.service.name");
}

@GetMapping(value = "/returnheaders", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String, String>> returnheaders(
@RequestHeader Map<String, String> headers) {
return ResponseEntity.ok(headers);
}

@GetMapping("/appsec/{id}")
public String pathParam(
@PathVariable("id") String id,
@RequestParam(name = "url", required = false) String url,
@RequestParam(name = "forceKeep", required = false) boolean forceKeep) {
if (forceKeep) {
forceKeepSpan();
}
if (url != null) {
RestTemplate restTemplate = new RestTemplate();
return restTemplate.getForObject(url, String.class);
}
return id;
}

@GetMapping("/iast")
@SuppressFBWarnings
public void write(
@RequestParam(name = "injection", required = false) String injection,
@RequestParam(name = "url", required = false) String url,
@RequestParam(name = "forceKeep", required = false) boolean forceKeep,
final HttpServletResponse response) {
if (forceKeep) {
forceKeepSpan();
}
if (injection != null) {
try {
response.getWriter().write(injection);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if (url != null) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getForObject(url, String.class);
}
}

private String forceKeepSpan() {
final Span span = GlobalTracer.get().activeSpan();
if (span != null) {
span.setTag("manual.keep", true);
return span.context().toSpanId();
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package datadog.smoketest.asmstandalonebilling;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package datadog.smoketest.asmstandalonebilling

import datadog.smoketest.AbstractServerSmokeTest
import datadog.trace.api.sampling.PrioritySampling
import datadog.trace.test.agent.decoder.DecodedTrace

abstract class AbstractAsmStandaloneBillingSmokeTest extends AbstractServerSmokeTest {

@Override
File createTemporaryFile(int processIndex) {
return null
}

@Override
String logLevel() {
return 'debug'
}

@Override
Closure decodedTracesCallback() {
return {} // force traces decoding
}

protected ProcessBuilder createProcess(String[] properties){
createProcess(-1, properties)
}


protected ProcessBuilder createProcess(int processIndex, String[] properties){
def port = processIndex == -1 ? httpPort : httpPorts[processIndex]
String springBootShadowJar = System.getProperty("datadog.smoketest.springboot.shadowJar.path")
List<String> command = []
command.add(javaPath())
command.addAll(defaultJavaProperties)
command.addAll(properties)
command.addAll((String[]) ['-jar', springBootShadowJar, "--server.port=${port}"])
ProcessBuilder processBuilder = new ProcessBuilder(command)
processBuilder.directory(new File(buildDirectory))
// Spring will print all environment variables to the log, which may pollute it and affect log assertions.
processBuilder.environment().clear()
return processBuilder
}

protected DecodedTrace getServiceTrace(String serviceName) {
return traces.find { trace ->
trace.spans.find { span ->
span.service == serviceName
}
}
}

protected DecodedTrace getServiceTraceFromUrl(String url) {
return traces.find { trace ->
trace.spans.find { span ->
span.meta["http.url"] == url
}
}
}

protected checkRootSpanPrioritySampling(DecodedTrace trace, byte priority) {
return trace.spans[0].metrics['_sampling_priority_v1'] == priority
}

protected isSampledBySampler(DecodedTrace trace) {
def samplingPriority = trace.spans[0].metrics['_sampling_priority_v1']
return samplingPriority == PrioritySampling.SAMPLER_KEEP || samplingPriority == PrioritySampling.SAMPLER_DROP
}

protected hasAppsecPropagationTag(DecodedTrace trace) {
return trace.spans[0].meta['_dd.p.appsec'] == "1"
jandro996 marked this conversation as resolved.
Show resolved Hide resolved
}

protected hasApmDisabledTag(DecodedTrace trace) {
return trace.spans[0].metrics['_dd.apm.enabled'] == 0
}

protected hasASMEvents(DecodedTrace trace){
return trace.spans[0].meta['_dd.iast.json'] != null || trace.spans[0].meta['_dd.appsec.json'] != null
}
}
Loading
Loading