From fbb3088f844704eb2ec6d0d648b5e71e566bbd54 Mon Sep 17 00:00:00 2001 From: Andrew Azores Date: Tue, 9 Apr 2024 10:10:50 -0400 Subject: [PATCH] fix(matchexpressions): correct endpoint case for JSON ID request filter (#356) * fix(matchexpressions): correct endpoint case for JSON ID request filter * allow IDs in per-rule request paths do not allow IDs in rule creation POSTS, but do allow in modification PATCHes - the ID field will be ignored here anyway --- .../java/io/cryostat/JsonRequestFilter.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/cryostat/JsonRequestFilter.java b/src/main/java/io/cryostat/JsonRequestFilter.java index a63ee9d675..36dec2f842 100644 --- a/src/main/java/io/cryostat/JsonRequestFilter.java +++ b/src/main/java/io/cryostat/JsonRequestFilter.java @@ -19,7 +19,10 @@ import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -33,9 +36,10 @@ public class JsonRequestFilter implements ContainerRequestFilter { static final Set disallowedFields = Set.of("id"); - static final Set allowedPaths = - Set.of("/api/v2.2/discovery", "/api/beta/matchexpressions"); + static final Set allowedPathPatterns = + Set.of("/api/v2.2/discovery", "/api/v2/rules/[\\w]+", "/api/beta/matchExpressions"); + private final Map compiledPatterns = new HashMap<>(); private final ObjectMapper objectMapper = new ObjectMapper(); @Override @@ -43,7 +47,7 @@ public void filter(ContainerRequestContext requestContext) throws IOException { if (requestContext.getMediaType() != null && requestContext.getMediaType().isCompatible(MediaType.APPLICATION_JSON_TYPE) && (requestContext.getUriInfo() != null - && !allowedPaths.contains(requestContext.getUriInfo().getPath()))) { + && !anyPatternMatch(requestContext.getUriInfo().getPath()))) { try (InputStream stream = requestContext.getEntityStream()) { JsonNode rootNode = objectMapper.readTree(stream); @@ -77,4 +81,13 @@ private boolean containsIdField(JsonNode node) { } return false; } + + private boolean anyPatternMatch(String path) { + var match = false; + for (var p : allowedPathPatterns) { + var pattern = compiledPatterns.computeIfAbsent(p, Pattern::compile); + match |= pattern.matcher(path).matches(); + } + return match; + } }