Skip to content
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import io.sentry.IProfileConverter
import io.sentry.IScopes
import io.sentry.ITransportFactory
import io.sentry.Integration
import io.sentry.KeyValueCollectionBehavior
import io.sentry.NoOpContinuousProfiler
import io.sentry.NoOpProfileConverter
import io.sentry.NoOpTransportFactory
Expand Down Expand Up @@ -306,6 +307,35 @@ class SentryAutoConfigurationTest {
}
}

@Test
fun `data collection key value properties are applied to SentryOptions`() {
contextRunner
.withPropertyValues(
"sentry.dsn=http://key@localhost/proj",
"sentry.data-collection.cookies.mode=off",
"sentry.data-collection.url-query-params.mode=allow-list",
"sentry.data-collection.url-query-params.terms=page,sort",
"sentry.data-collection.http-headers.request.mode=deny-list",
"sentry.data-collection.http-headers.request.terms=forwarded,-ip",
"sentry.data-collection.http-headers.response.mode=allow-list",
"sentry.data-collection.http-headers.response.terms=content-type,x-request-id",
)
.run {
val dataCollection = it.getBean(SentryProperties::class.java).dataCollection
assertThat(dataCollection.cookies!!.mode).isEqualTo(KeyValueCollectionBehavior.Mode.OFF)
assertThat(dataCollection.urlQueryParams!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.ALLOW_LIST)
assertThat(dataCollection.urlQueryParams!!.terms).containsExactly("page", "sort")
assertThat(dataCollection.httpHeaders.request!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.DENY_LIST)
assertThat(dataCollection.httpHeaders.request!!.terms).containsExactly("forwarded", "-ip")
assertThat(dataCollection.httpHeaders.response!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.ALLOW_LIST)
assertThat(dataCollection.httpHeaders.response!!.terms)
.containsExactly("content-type", "x-request-id")
}
}

@Test
fun `when tracePropagationTargets are not set, default is returned`() {
contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import io.sentry.IProfileConverter
import io.sentry.IScopes
import io.sentry.ITransportFactory
import io.sentry.Integration
import io.sentry.KeyValueCollectionBehavior
import io.sentry.NoOpContinuousProfiler
import io.sentry.NoOpProfileConverter
import io.sentry.NoOpTransportFactory
Expand Down Expand Up @@ -314,6 +315,35 @@ class SentryAutoConfigurationTest {
}
}

@Test
fun `data collection key value properties are applied to SentryOptions`() {
contextRunner
.withPropertyValues(
"sentry.dsn=http://key@localhost/proj",
"sentry.data-collection.cookies.mode=off",
"sentry.data-collection.url-query-params.mode=allow-list",
"sentry.data-collection.url-query-params.terms=page,sort",
"sentry.data-collection.http-headers.request.mode=deny-list",
"sentry.data-collection.http-headers.request.terms=forwarded,-ip",
"sentry.data-collection.http-headers.response.mode=allow-list",
"sentry.data-collection.http-headers.response.terms=content-type,x-request-id",
)
.run {
val dataCollection = it.getBean(SentryProperties::class.java).dataCollection
assertThat(dataCollection.cookies!!.mode).isEqualTo(KeyValueCollectionBehavior.Mode.OFF)
assertThat(dataCollection.urlQueryParams!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.ALLOW_LIST)
assertThat(dataCollection.urlQueryParams!!.terms).containsExactly("page", "sort")
assertThat(dataCollection.httpHeaders.request!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.DENY_LIST)
assertThat(dataCollection.httpHeaders.request!!.terms).containsExactly("forwarded", "-ip")
assertThat(dataCollection.httpHeaders.response!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.ALLOW_LIST)
assertThat(dataCollection.httpHeaders.response!!.terms)
.containsExactly("content-type", "x-request-id")
}
}

@Test
fun `when tracePropagationTargets are not set, default is returned`() {
contextRunner.withPropertyValues("sentry.dsn=http://key@localhost/proj").run {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import io.sentry.IProfileConverter
import io.sentry.IScopes
import io.sentry.ITransportFactory
import io.sentry.Integration
import io.sentry.KeyValueCollectionBehavior
import io.sentry.NoOpContinuousProfiler
import io.sentry.NoOpProfileConverter
import io.sentry.NoOpTransportFactory
Expand Down Expand Up @@ -312,6 +313,35 @@ class SentryAutoConfigurationTest {
}
}

@Test
fun `data collection key value properties are applied to SentryOptions`() {
contextRunner
.withPropertyValues(
"sentry.dsn=http://key@localhost/proj",
"sentry.data-collection.cookies.mode=off",
"sentry.data-collection.url-query-params.mode=allow-list",
"sentry.data-collection.url-query-params.terms=page,sort",
"sentry.data-collection.http-headers.request.mode=deny-list",
"sentry.data-collection.http-headers.request.terms=forwarded,-ip",
"sentry.data-collection.http-headers.response.mode=allow-list",
"sentry.data-collection.http-headers.response.terms=content-type,x-request-id",
)
.run {
val dataCollection = it.getBean(SentryProperties::class.java).dataCollection
assertThat(dataCollection.cookies!!.mode).isEqualTo(KeyValueCollectionBehavior.Mode.OFF)
assertThat(dataCollection.urlQueryParams!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.ALLOW_LIST)
assertThat(dataCollection.urlQueryParams!!.terms).containsExactly("page", "sort")
assertThat(dataCollection.httpHeaders.request!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.DENY_LIST)
assertThat(dataCollection.httpHeaders.request!!.terms).containsExactly("forwarded", "-ip")
assertThat(dataCollection.httpHeaders.response!!.mode)
.isEqualTo(KeyValueCollectionBehavior.Mode.ALLOW_LIST)
assertThat(dataCollection.httpHeaders.response!!.terms)
.containsExactly("content-type", "x-request-id")
}
}

@Test
fun `when tracePropagationTargets are not set, default is returned`() {
dsnEnabledRunner.run {
Expand Down
3 changes: 3 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1446,13 +1446,16 @@ public abstract interface class io/sentry/JsonUnknown {
}

public final class io/sentry/KeyValueCollectionBehavior {
public fun <init> ()V
public static fun allowList ([Ljava/lang/String;)Lio/sentry/KeyValueCollectionBehavior;
public static fun denyList ([Ljava/lang/String;)Lio/sentry/KeyValueCollectionBehavior;
public fun equals (Ljava/lang/Object;)Z
public fun getMode ()Lio/sentry/KeyValueCollectionBehavior$Mode;
public fun getTerms ()Ljava/util/List;
public fun hashCode ()I
public static fun off ()Lio/sentry/KeyValueCollectionBehavior;
public fun setMode (Lio/sentry/KeyValueCollectionBehavior$Mode;)V
public fun setTerms (Ljava/util/List;)V
}

public final class io/sentry/KeyValueCollectionBehavior$Mode : java/lang/Enum {
Expand Down
19 changes: 15 additions & 4 deletions sentry/src/main/java/io/sentry/KeyValueCollectionBehavior.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@ public enum Mode {
ALLOW_LIST
}

private final @NotNull Mode mode;
private final @NotNull List<String> terms;
private @NotNull Mode mode = Mode.DENY_LIST;
private @NotNull List<String> terms = Collections.emptyList();

/** Creates a behavior that collects values using the built-in sensitive deny-list. */
public KeyValueCollectionBehavior() {}

private KeyValueCollectionBehavior(final @NotNull Mode mode, final @NotNull List<String> terms) {
this.mode = mode;
this.terms = Collections.unmodifiableList(new ArrayList<>(terms));
setMode(mode);
setTerms(terms);
}

/** Disables collection of the category. */
Expand Down Expand Up @@ -53,10 +56,18 @@ private KeyValueCollectionBehavior(final @NotNull Mode mode, final @NotNull List
return mode;
}

public void setMode(final @NotNull Mode mode) {
this.mode = mode;
}

public @NotNull List<String> getTerms() {
return terms;
}

public void setTerms(final @NotNull List<String> terms) {
this.terms = Collections.unmodifiableList(new ArrayList<>(terms));
}

@Override
public boolean equals(final Object other) {
if (this == other) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@ import com.google.common.truth.Truth.assertThat
import kotlin.test.Test

class KeyValueCollectionBehaviorTest {
@Test
fun `default constructor uses deny list with no terms`() {
val behavior = KeyValueCollectionBehavior()

assertThat(behavior.mode).isEqualTo(KeyValueCollectionBehavior.Mode.DENY_LIST)
assertThat(behavior.terms).isEmpty()
}

@Test
fun `setters update mode and defensively copy terms`() {
val terms = mutableListOf("token")
val behavior = KeyValueCollectionBehavior()

behavior.mode = KeyValueCollectionBehavior.Mode.ALLOW_LIST
behavior.terms = terms
terms[0] = "password"

assertThat(behavior.mode).isEqualTo(KeyValueCollectionBehavior.Mode.ALLOW_LIST)
assertThat(behavior.terms).containsExactly("token")
}

@Test
fun `off has no terms`() {
val behavior = KeyValueCollectionBehavior.off()
Expand Down
Loading