aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@vespa.ai>2024-06-06 11:33:21 +0200
committerBjørn Christian Seime <bjorncs@vespa.ai>2024-06-06 11:40:41 +0200
commit64678270e5ac9ab3a9f2b6523b4c2fc80999c4d9 (patch)
treeba021fc81560692b7860b877ddce0007182e3536
parentcf00a65940560c8fbfe32a015f4ef50942e997d8 (diff)
Validate flag content with a stricter regex
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/Flags.java10
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/JacksonArraySerializer.java11
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java6
-rw-r--r--flags/src/main/java/com/yahoo/vespa/flags/UnboundListFlag.java8
4 files changed, 32 insertions, 3 deletions
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
index df307b581f1..c207fd63dbd 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/Flags.java
@@ -12,6 +12,7 @@ import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Optional;
import java.util.TreeMap;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import static com.yahoo.vespa.flags.Dimension.APPLICATION;
@@ -528,6 +529,15 @@ public class Flags {
flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions);
}
+ /** WARNING: public for testing: All flags should be defined in {@link Flags}. */
+ public static <T> UnboundListFlag<T> defineListFlag(String flagId, List<T> defaultValue, Class<T> elementClass,
+ List<String> owners, String createdAt, String expiresAt,
+ String description, String modificationEffect,
+ Predicate<List<T>> validator, Dimension... dimensions) {
+ return define((fid, dval, fvec) -> new UnboundListFlag<>(fid, dval, elementClass, fvec, validator),
+ flagId, defaultValue, owners, createdAt, expiresAt, description, modificationEffect, dimensions);
+ }
+
@FunctionalInterface
private interface TypedUnboundFlagFactory<T, U extends UnboundFlag<?, ?, ?>> {
U create(FlagId id, T defaultValue, FetchVector defaultFetchVector);
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/JacksonArraySerializer.java b/flags/src/main/java/com/yahoo/vespa/flags/JacksonArraySerializer.java
index 8f7b7d71734..38e3b57d28b 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/JacksonArraySerializer.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/JacksonArraySerializer.java
@@ -4,20 +4,27 @@ package com.yahoo.vespa.flags;
import com.fasterxml.jackson.databind.JavaType;
import java.util.List;
+import java.util.function.Predicate;
/**
* @author freva
*/
public class JacksonArraySerializer<T> implements FlagSerializer<List<T>> {
private final JavaType type;
+ private final Predicate<List<T>> validator;
- public JacksonArraySerializer(Class<T> clazz) {
+ public JacksonArraySerializer(Class<T> clazz, Predicate<List<T>> validator) {
type = JsonNodeRawFlag.constructCollectionType(List.class, clazz);
+ this.validator = validator;
}
@Override
public List<T> deserialize(RawFlag rawFlag) {
- return JsonNodeRawFlag.fromJsonNode(rawFlag.asJsonNode()).toJacksonClass(type);
+ var list = JsonNodeRawFlag.fromJsonNode(rawFlag.asJsonNode()).<List<T>>toJacksonClass(type);
+ if (!validator.test(list)) {
+ throw new IllegalArgumentException("Invalid value: " + list);
+ }
+ return list;
}
@Override
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
index fb807d186eb..19888ec362d 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/PermanentFlags.java
@@ -459,6 +459,7 @@ public class PermanentFlags {
"log-request-content", List.of(), String.class,
"Include request content in access log for paths starting with any of these prefixes",
"Takes effect on next redeployment",
+ list -> list.stream().allMatch(s -> s.matches("^[a-zA-Z/\\.0-9]+:(0(\\.\\d+)?|1(\\.0+)?):\\d+(B|kB|MB|GB)?$")),
INSTANCE_ID);
private PermanentFlags() {}
@@ -503,5 +504,10 @@ public class PermanentFlags {
return Flags.defineListFlag(flagId, defaultValue, elementClass, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, dimensions);
}
+ private static <T> UnboundListFlag<T> defineListFlag(
+ String flagId, List<T> defaultValue, Class<T> elementClass, String description, String modificationEffect, Predicate<List<T>> validator, Dimension... dimensions) {
+ return Flags.defineListFlag(flagId, defaultValue, elementClass, OWNERS, toString(CREATED_AT), toString(EXPIRES_AT), description, modificationEffect, validator, dimensions);
+ }
+
private static String toString(Instant instant) { return DateTimeFormatter.ISO_DATE.withZone(ZoneOffset.UTC).format(instant); }
}
diff --git a/flags/src/main/java/com/yahoo/vespa/flags/UnboundListFlag.java b/flags/src/main/java/com/yahoo/vespa/flags/UnboundListFlag.java
index f88a0648021..8411a286d54 100644
--- a/flags/src/main/java/com/yahoo/vespa/flags/UnboundListFlag.java
+++ b/flags/src/main/java/com/yahoo/vespa/flags/UnboundListFlag.java
@@ -2,6 +2,7 @@
package com.yahoo.vespa.flags;
import java.util.List;
+import java.util.function.Predicate;
/**
* @author freva
@@ -12,8 +13,13 @@ public class UnboundListFlag<T> extends UnboundFlagImpl<List<T>, ListFlag<T>, Un
}
public UnboundListFlag(FlagId id, List<T> defaultValue, Class<T> clazz, FetchVector defaultFetchVector) {
+ this(id, defaultValue, clazz, defaultFetchVector, __ -> true);
+ }
+
+ public UnboundListFlag(FlagId id, List<T> defaultValue, Class<T> clazz, FetchVector defaultFetchVector,
+ Predicate<List<T>> validator) {
super(id, defaultValue, defaultFetchVector,
- new JacksonArraySerializer<T>(clazz),
+ new JacksonArraySerializer<T>(clazz, validator),
(flagId, defVal, fetchVector) -> new UnboundListFlag<>(flagId, defVal, clazz, fetchVector),
ListFlag::new);
}