Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<commons.validator.version>1.6</commons.validator.version>
<commons-io.version>2.16.1</commons-io.version>
<commons-csv.version>1.4</commons-csv.version>
<commons-jexl.version>3.0</commons-jexl.version>
<commons-jexl.version>3.1</commons-jexl.version>
<commons-lang.version>2.6</commons-lang.version>
<commons-lang3.version>3.5</commons-lang3.version>
<commons-math3.version>3.6.1</commons-math3.version>
Expand Down
6 changes: 5 additions & 1 deletion wrangler-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
<version>${cdap.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright © 2026 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package io.cdap.wrangler.api;

Comment thread
vsethi09 marked this conversation as resolved.
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* Defines the set of classes allowed in the JEXL Sandbox by default.
*/
public final class DefaultJexlAllowlist {

private static final List<String> DEFAULT_CLASSES = Arrays.asList(
// Data types
"java.lang.Boolean", "java.lang.Byte", "java.lang.Character", "java.lang.Double", "java.lang.Float",
"java.lang.Integer", "java.lang.Long", "java.lang.Short",

// Strings
"java.lang.String", "java.lang.StringBuilder", "java.util.StringJoiner",

// Math
"java.lang.Math", "java.math.BigDecimal", "java.math.BigInteger",

// Time
"java.time.ZonedDateTime", "java.time.LocalDate", "java.time.LocalDateTime", "java.time.Instant",
"java.time.Duration", "java.time.format.DateTimeFormatter",

// Utilities
"java.util.Arrays", "java.util.Collections", "java.util.UUID", "java.util.Base64");

private static final List<JexlAllowlist> ALLOWLIST = Collections.unmodifiableList(
DEFAULT_CLASSES.stream()
.map(className -> {
return new JexlAllowlist(
Objects.requireNonNull(className),
Collections.singletonList(JexlAllowlist.INCLUDE_ALL_WILDCARD),
Collections.singletonList(JexlAllowlist.INCLUDE_ALL_WILDCARD));
})
.collect(Collectors.toList()));

private DefaultJexlAllowlist() {
}

/**
* @return the list of default allowed classes.
*/
public static List<JexlAllowlist> get() {
Comment thread
riyaa14 marked this conversation as resolved.
Comment thread
vsethi09 marked this conversation as resolved.
return ALLOWLIST;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,29 @@

package io.cdap.wrangler.api;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
* This class {@link DirectiveConfig} defines the configuration for the Wrangler.
* This class {@link DirectiveConfig} defines the configuration for the
* Wrangler.
* It specifies the directive exclusions -- meaning directives that should
* not be accessible to the users and as well as directive aliases.
*
Expand All @@ -42,18 +52,69 @@
* "aliases" : {
* "json-parser" : "parse-as-json",
* "js-parser" : "parse-as-json"
* },
* "jexlAllowlist" : [
* {
* "className": "java.lang.Runtime",
* "methods": ["*"],
* "properties": ["*"]
* }
* ]
* }
*/
@Deprecated
public final class DirectiveConfig {
public static final DirectiveConfig EMPTY = new DirectiveConfig();
// RecipeParser to be excluded or made non-accessible.
private final Set<String> exclusions = new HashSet<>();
public static final DirectiveConfig EMPTY = new DirectiveConfig(null, null, Collections.emptyList());
public static final String EXCLUSIONS_KEY = "exclusions";
public static final String ALIASES_KEY = "aliases";
public static final String JEXL_ALLOWLIST_KEY = "jexlAllowlist";

// RecipeParser to be aliased.
private final Map<String, String> aliases = new HashMap<>();
private final ImmutableSet<String> exclusions;
private final ImmutableMap<String, String> aliases;
@Nullable private final ImmutableList<JexlAllowlist> jexlAllowlist;

private DirectiveConfig(
@Nullable Set<String> exclusions,
@Nullable Map<String, String> aliases,
@Nullable List<JexlAllowlist> jexlAllowlist) {
this.exclusions = exclusions != null ? ImmutableSet.copyOf(exclusions) : ImmutableSet.of();
this.aliases = aliases != null ? ImmutableMap.copyOf(aliases) : ImmutableMap.of();
this.jexlAllowlist = jexlAllowlist != null ? ImmutableList.copyOf(jexlAllowlist) : null;
}

/** Custom GSON adapter for {@link DirectiveConfig}. */
public static final class DirectiveConfigDeserializer implements JsonDeserializer<DirectiveConfig> {

@Override
public DirectiveConfig deserialize(JsonElement configJson, Type typeOfT, JsonDeserializationContext ctx)
throws JsonParseException {
JsonObject configJsonObj = configJson.getAsJsonObject();

return new DirectiveConfig(
deserializeProperty(configJsonObj, EXCLUSIONS_KEY, new TypeToken<Set<String>>() {
}.getType(), ctx),
deserializeProperty(configJsonObj, ALIASES_KEY, new TypeToken<Map<String, String>>() {
}.getType(), ctx),
deserializeProperty(configJsonObj, JEXL_ALLOWLIST_KEY, new TypeToken<List<JexlAllowlist>>() {
}.getType(), ctx));
}

@Nullable
private static <T> T deserializeProperty(JsonObject obj, String key, Type type, JsonDeserializationContext ctx) {
JsonElement element = obj.get(key);
return (element != null && !element.isJsonNull()) ? ctx.deserialize(element, type) : null;
}
}

/**
* Gets the list of JEXL inclusions.
*
* @return the list of JEXL inclusions
*/
@Nullable
public List<JexlAllowlist> getJexlAllowlist() {
return jexlAllowlist == null ? null : Collections.unmodifiableList(jexlAllowlist);
}

/**
* Checks if a directive is aliased.
Expand Down Expand Up @@ -108,8 +169,9 @@ public boolean isExcluded(String directive) {
public JsonElement toJson() {
Gson gson = new Gson();
JsonObject object = new JsonObject();
object.add("exclusions", gson.toJsonTree(exclusions));
object.add("aliases", gson.toJsonTree(aliases));
object.add(EXCLUSIONS_KEY, gson.toJsonTree(exclusions));
object.add(ALIASES_KEY, gson.toJsonTree(aliases));
object.add(JEXL_ALLOWLIST_KEY, gson.toJsonTree(jexlAllowlist));
return object;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
* {@link DirectiveContext} provides the context object to the processing of
* directives.
*/
public interface DirectiveContext extends DirectiveEnforcer, DirectiveAlias {
public interface DirectiveContext extends DirectiveEnforcer, DirectiveAlias, DirectiveJexlAllowlist {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright © 2026 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package io.cdap.wrangler.api;

import java.util.List;

/**
* This interface {@link DirectiveJexlAllowlist} provides a way to get JEXL
* configuration.
*/
public interface DirectiveJexlAllowlist {

/**
* Gets the list of JEXL inclusions.
*
* @return the list of JEXL inclusions
*/
List<JexlAllowlist> getJexlAllowlist();

/**
* Checks if JEXL allowlisting is enabled.
*
* @return true if JEXL allowlisting is enabled, false otherwise.
*/
boolean isJexlAllowlistEnabled();
}
Loading
Loading