From 35f4f61e53caaaf334232a682f7f8e78a34460a0 Mon Sep 17 00:00:00 2001 From: "sezen.leblay" Date: Mon, 30 Jun 2025 11:07:08 +0200 Subject: [PATCH 1/3] Create activation origin config for telemetry Signed-off-by: sezen.leblay --- .../com/datadog/appsec/config/AppSecConfigServiceImpl.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java index 880b6c45528..4d6eb78f864 100644 --- a/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java +++ b/dd-java-agent/appsec/src/main/java/com/datadog/appsec/config/AppSecConfigServiceImpl.java @@ -21,6 +21,7 @@ import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_TRUSTED_IPS; import static datadog.remoteconfig.Capabilities.CAPABILITY_ASM_USER_BLOCKING; import static datadog.remoteconfig.Capabilities.CAPABILITY_ENDPOINT_FINGERPRINT; +import static datadog.trace.api.config.AppSecConfig.APPSEC_ENABLED; import com.datadog.appsec.AppSecModule; import com.datadog.appsec.AppSecSystem; @@ -45,6 +46,8 @@ import datadog.remoteconfig.state.ConfigKey; import datadog.remoteconfig.state.ProductListener; import datadog.trace.api.Config; +import datadog.trace.api.ConfigCollector; +import datadog.trace.api.ConfigOrigin; import datadog.trace.api.ProductActivation; import datadog.trace.api.UserIdCollectionMode; import datadog.trace.api.telemetry.LogCollector; @@ -517,6 +520,8 @@ private void setAppSecActivation(final AppSecFeatures.Asm asm) { newState = tracerConfig.getAppSecActivation() == ProductActivation.FULLY_ENABLED; } else { newState = asm.enabled; + // Report AppSec activation change via telemetry when modified via remote config + ConfigCollector.get().put(APPSEC_ENABLED, asm.enabled, ConfigOrigin.REMOTE); } if (AppSecSystem.isActive() != newState) { log.info("AppSec {} (runtime)", newState ? "enabled" : "disabled"); From 9df1e9908c43e9170d35ef62868bb3d71bba7e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Fri, 11 Jul 2025 14:27:58 +0200 Subject: [PATCH 2/3] Add smoke test --- .../dynamicconfig/AppSecApplication.java | 14 +++++++ .../AppSecActivationSmokeTest.groovy | 39 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 dd-smoke-tests/dynamic-config/src/main/java/datadog/smoketest/dynamicconfig/AppSecApplication.java create mode 100644 dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy diff --git a/dd-smoke-tests/dynamic-config/src/main/java/datadog/smoketest/dynamicconfig/AppSecApplication.java b/dd-smoke-tests/dynamic-config/src/main/java/datadog/smoketest/dynamicconfig/AppSecApplication.java new file mode 100644 index 00000000000..65367491985 --- /dev/null +++ b/dd-smoke-tests/dynamic-config/src/main/java/datadog/smoketest/dynamicconfig/AppSecApplication.java @@ -0,0 +1,14 @@ +package datadog.smoketest.dynamicconfig; + +import java.util.concurrent.TimeUnit; + +public class AppSecApplication { + + public static final long TIMEOUT_IN_SECONDS = 10; + + public static void main(String[] args) throws InterruptedException { + // just wait as we want to test RC payloads + Thread.sleep(TimeUnit.SECONDS.toMillis(TIMEOUT_IN_SECONDS)); + System.exit(0); + } +} diff --git a/dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy b/dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy new file mode 100644 index 00000000000..21d33affa15 --- /dev/null +++ b/dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy @@ -0,0 +1,39 @@ +package datadog.smoketest + +import datadog.smoketest.dynamicconfig.AppSecApplication + +class AppSecActivationSmokeTest extends AbstractSmokeTest { + + @Override + ProcessBuilder createProcessBuilder() { + def command = [javaPath()] + command += defaultJavaProperties.toList() + command += [ + '-Ddd.remote_config.enabled=true', + "-Ddd.remote_config.url=http://localhost:${server.address.port}/v0.7/config".toString(), + '-Ddd.remote_config.poll_interval.seconds=1', + '-cp', + System.getProperty('datadog.smoketest.shadowJar.path'), + AppSecApplication.name + ] + + final processBuilder = new ProcessBuilder(command) + processBuilder.directory(new File(buildDirectory)) + } + + void 'test activation config change is sent via RC'() { + when: + setRemoteConfig('datadog/2/ASM_FEATURES/asm_features_activation/config', '{"asm":{"enabled":true}}') + + then: + waitForTelemetryFlat { + if (it['request_type'] != 'app-client-configuration-change') { + return false + } + final payload = (Map) it['payload'] + final configurations = (List>) payload['configuration'] + final enabled = configurations.find { it['name'] == 'appsec_enabled' } + return enabled['value'] == 'true' && enabled['origin'] == 'remote_config' + } + } +} From 1a8ee07e9a38f53af1aa690175434444c55e7ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20=C3=81lvarez=20=C3=81lvarez?= Date: Wed, 16 Jul 2025 12:11:27 +0200 Subject: [PATCH 3/3] Fix failing remote config test --- .../smoketest/AppSecActivationSmokeTest.groovy | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy b/dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy index 21d33affa15..813bb424f82 100644 --- a/dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy +++ b/dd-smoke-tests/dynamic-config/src/test/groovy/datadog/smoketest/AppSecActivationSmokeTest.groovy @@ -12,6 +12,7 @@ class AppSecActivationSmokeTest extends AbstractSmokeTest { '-Ddd.remote_config.enabled=true', "-Ddd.remote_config.url=http://localhost:${server.address.port}/v0.7/config".toString(), '-Ddd.remote_config.poll_interval.seconds=1', + '-Ddd.profiling.enabled=false', '-cp', System.getProperty('datadog.smoketest.shadowJar.path'), AppSecApplication.name @@ -30,10 +31,12 @@ class AppSecActivationSmokeTest extends AbstractSmokeTest { if (it['request_type'] != 'app-client-configuration-change') { return false } - final payload = (Map) it['payload'] - final configurations = (List>) payload['configuration'] - final enabled = configurations.find { it['name'] == 'appsec_enabled' } - return enabled['value'] == 'true' && enabled['origin'] == 'remote_config' + final configurations = (List>) it?.payload?.configuration ?: [] + final enabledConfig = configurations.find { it.name == 'appsec_enabled' } + if (!enabledConfig) { + return false + } + return enabledConfig.value == 'true' && enabledConfig .origin == 'remote_config' } } }