This is an automated email from the ASF dual-hosted git repository.
ctubbsii pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/accumulo-classloaders.git
The following commit(s) were added to refs/heads/main by this push:
new 2040075 Add allowed URLs security property (#55)
2040075 is described below
commit 204007565085030ad1b4fc6c6a72378f115d28aa
Author: Christopher Tubbs <[email protected]>
AuthorDate: Fri Jan 30 19:15:46 2026 -0500
Add allowed URLs security property (#55)
To mitigate the risks of file disclosure vulnerabilities, a property is
added to ensure the library cannot copy data from unapproved sources,
into the local cache directory.
---
modules/local-caching-classloader/README.md | 28 +++++++-
.../lcc/LocalCachingContextClassLoaderFactory.java | 37 ++++++++++-
.../accumulo/classloader/lcc/util/LocalStore.java | 11 +++-
.../LocalCachingContextClassLoaderFactoryTest.java | 75 ++++++++++++++++------
.../MiniAccumuloClusterClassLoaderFactoryTest.java | 2 +
.../classloader/lcc/util/LocalStoreTest.java | 25 +++++---
6 files changed, 142 insertions(+), 36 deletions(-)
diff --git a/modules/local-caching-classloader/README.md
b/modules/local-caching-classloader/README.md
index a624386..988e947 100644
--- a/modules/local-caching-classloader/README.md
+++ b/modules/local-caching-classloader/README.md
@@ -111,8 +111,8 @@ exist in the de-duplicating cache).
## Local Storage Cache
The local storage cache location is configured by the user by setting the
-Accumulo property named `general.custom.classloader.lcc.cache.dir` to a
-directory on the local filesystem. This location may be specified as an
+required Accumulo property named `general.custom.classloader.lcc.cache.dir` to
+a directory on the local filesystem. This location may be specified as an
absolute path or as a URL representing an absolute path with the `file` scheme.
The selected location should be a persistent location with plenty of space to
@@ -131,6 +131,29 @@ unexpected behavior to classloaders still using the file.
* The local storage cache location **MUST** use a filesystem that supports
atomic moves.
+## Security
+
+The Accumulo property `general.custom.classloader.lcc.allowed.urls.pattern` is
+another required parameter. It is used to limit the allowed URLs that can be
+fetched when downloading context definitions or context resources. Since the
+process using this factory will be using its own permissions to fetch
+resources, and placing a copy of those resources in a local directory where
+others may access them, that presents presents a potential file disclosure
+security risk. This property allows a system administrator to mitigate that
+risk by restricting access to only approved URLs. (e.g. to exclude non-approved
+locations like `file:/path/to/accumulo.properties` or
+`hdfs://host/path/to/accumulo/rfile.rf`).
+
+An example value for this property might look like:
+`https://example.com/path/to/contexts/.*` or
+`(file:/etc|hdfs://example[.]com:9000)/path/to/contexts/.*`
+
+Note: this property affects all URLs fetched by this factory, including context
+definition URLs and any resource URLs defined inside any fetched context
+definition. It should be updated by a system maintainer if any new context
+definitions have need to use new locations. It may be updated on a running
+system, and will take effect after approximately a minute.
+
## Creating a ContextDefinition file
Users may take advantage of the `ContextDefinition.create(int,String,URL[])`
@@ -224,6 +247,7 @@ To use this with Accumulo:
1. Set the following Accumulo properties:
*
`general.context.class.loader.factory=org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory`
* `general.custom.classloader.lcc.cache.dir=file://path/to/some/directory`
+ *
`general.custom.classloader.lcc.allowed.urls.pattern=someRegexPatternForAllowedUrls`
2. Set the following table property to link to a context definition file. For
example:
*
`table.class.loader.context=(file|hdfs|http|https)://path/to/context/definition.json`
diff --git
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
index dd232c1..f0d54b0 100644
---
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
+++
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactory.java
@@ -37,7 +37,9 @@ import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
import java.util.function.Supplier;
+import java.util.regex.Pattern;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
@@ -59,6 +61,7 @@ import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
+import com.google.common.base.Suppliers;
/**
* A ContextClassLoaderFactory implementation that creates and maintains a
ClassLoader for a context
@@ -77,7 +80,8 @@ import com.google.common.base.Stopwatch;
* resource URL and caches it in a directory on the local filesystem. This
class uses the value of
* the property {@link #CACHE_DIR_PROPERTY} passed via {@link
#init(ContextClassLoaderEnvironment)}
* as the root directory and creates a sub-directory for context definition
files, and another for
- * resource files. All cached files have a name that includes their checksum.
+ * resource files. All cached files have a name that includes their checksum.
The required property,
+ * {@link #ALLOWED_URLS_PATTERN}, is used to specify a pattern for allowed
URLs to be fetched.
* <p>
* An in-progress signal file is used for each resource file while it is being
downloaded, to allow
* multiple processes or threads to try to avoid redundant downloads. Atomic
filesystem moves are
@@ -94,6 +98,9 @@ public class LocalCachingContextClassLoaderFactory implements
ContextClassLoader
public static final String UPDATE_FAILURE_GRACE_PERIOD_MINS =
"general.custom.classloader.lcc.update.grace.minutes";
+ public static final String ALLOWED_URLS_PATTERN =
+ "general.custom.classloader.lcc.allowed.urls.pattern";
+
private static final Logger LOG =
LoggerFactory.getLogger(LocalCachingContextClassLoaderFactory.class);
@@ -114,6 +121,9 @@ public class LocalCachingContextClassLoaderFactory
implements ContextClassLoader
private final Map<String,Stopwatch> classloaderFailures = new HashMap<>();
private volatile Duration updateFailureGracePeriodMins;
+ // this is a BiConsumer so we can pass a type in the String
+ private volatile BiConsumer<String,URL> allowedUrlChecker;
+
/**
* Schedule a task to execute at {@code interval} seconds to update the
LocalCachingContext if the
* ContextDefinition has changed. The task schedules a follow-on task at the
update interval value
@@ -144,6 +154,26 @@ public class LocalCachingContextClassLoaderFactory
implements ContextClassLoader
String graceProp =
env.getConfiguration().get(UPDATE_FAILURE_GRACE_PERIOD_MINS);
long graceMins = graceProp == null ? 0 : Long.parseLong(graceProp);
updateFailureGracePeriodMins = Duration.ofMinutes(graceMins);
+ // limit the frequency at which we check the config and re-compile the
pattern
+ Supplier<Pattern> allowedUrlsPattern = Suppliers.memoizeWithExpiration(
+ () ->
Pattern.compile(requireNonNull(env.getConfiguration().get(ALLOWED_URLS_PATTERN),
+ "Property " + ALLOWED_URLS_PATTERN + " not set, no URLs are
allowed")),
+ Duration.ofMinutes(1));
+ allowedUrlChecker = (locationType, url) -> {
+ var p = allowedUrlsPattern.get();
+ Preconditions.checkArgument(p.matcher(url.toExternalForm()).matches(),
+ "%s location (%s) not allowed by pattern (%s)", locationType,
url.toExternalForm(),
+ p.pattern());
+ };
+ try {
+ // check the allowed URLs pattern, getting it ready for first use, and
warning if it is bad
+ allowedUrlsPattern.get();
+ } catch (RuntimeException npe) {
+ LOG.warn(
+ "Property {} is not set or contains an invalid pattern ()."
+ + " No ClassLoader instances will be created until it is set.",
+ ALLOWED_URLS_PATTERN,
env.getConfiguration().get(ALLOWED_URLS_PATTERN), npe);
+ }
final Path baseCacheDir;
if (value.startsWith("file:")) {
try {
@@ -159,7 +189,7 @@ public class LocalCachingContextClassLoaderFactory
implements ContextClassLoader
"Base directory is neither a file URL nor an absolute file path: " +
value);
}
try {
- localStore.set(new LocalStore(baseCacheDir));
+ localStore.set(new LocalStore(baseCacheDir, allowedUrlChecker));
} catch (IOException e) {
throw new UncheckedIOException("Unable to create the local storage area
at " + baseCacheDir,
e);
@@ -225,9 +255,10 @@ public class LocalCachingContextClassLoaderFactory
implements ContextClassLoader
return computedDefinition;
}
- private static ContextDefinition getDefinition(String contextLocation)
throws IOException {
+ private ContextDefinition getDefinition(String contextLocation) throws
IOException {
LOG.trace("Retrieving context definition file from {}", contextLocation);
URL url = new URL(contextLocation);
+ allowedUrlChecker.accept("Context definition", url);
return ContextDefinition.fromRemoteURL(url);
}
diff --git
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
index 81cedad..40a143a 100644
---
a/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
+++
b/modules/local-caching-classloader/src/main/java/org/apache/accumulo/classloader/lcc/util/LocalStore.java
@@ -46,6 +46,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.function.BiConsumer;
import java.util.regex.Pattern;
import org.apache.accumulo.classloader.lcc.definition.ContextDefinition;
@@ -91,10 +92,13 @@ public final class LocalStore {
private final Path contextsDir;
private final Path resourcesDir;
+ private final BiConsumer<String,URL> allowedUrlChecker;
- public LocalStore(final Path baseDir) throws IOException {
+ public LocalStore(final Path baseDir, final BiConsumer<String,URL>
allowedUrlChecker)
+ throws IOException {
this.contextsDir =
requireNonNull(baseDir).toAbsolutePath().resolve("contexts");
this.resourcesDir = baseDir.resolve("resources");
+ this.allowedUrlChecker = requireNonNull(allowedUrlChecker);
Files.createDirectories(contextsDir);
Files.createDirectories(resourcesDir);
}
@@ -301,10 +305,13 @@ public final class LocalStore {
@SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD",
justification = "user-supplied URL is the intended functionality")
private void downloadFile(Path tempPath, Resource resource) {
+ URL url = resource.getLocation();
+ allowedUrlChecker.accept("Resource", url);
+
// CREATE_NEW ensures the temporary file name is unique for this attempt
// SYNC ensures file integrity on each write, in case of system failure.
Buffering minimizes
// system calls te read/write data which minimizes the number of syncs.
- try (var in = new BufferedInputStream(resource.getLocation().openStream(),
DL_BUFF_SIZE);
+ try (var in = new BufferedInputStream(url.openStream(), DL_BUFF_SIZE);
var out = new BufferedOutputStream(Files.newOutputStream(tempPath,
CREATE_NEW, WRITE, SYNC),
DL_BUFF_SIZE)) {
in.transferTo(out);
diff --git
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
index 72d8824..8354376 100644
---
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
+++
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/LocalCachingContextClassLoaderFactoryTest.java
@@ -18,6 +18,7 @@
*/
package org.apache.accumulo.classloader.lcc;
+import static
org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory.ALLOWED_URLS_PATTERN;
import static
org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory.CACHE_DIR_PROPERTY;
import static
org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory.UPDATE_FAILURE_GRACE_PERIOD_MINS;
import static
org.apache.accumulo.classloader.lcc.TestUtils.createContextDefinitionFile;
@@ -168,11 +169,53 @@ public class LocalCachingContextClassLoaderFactoryTest {
public void beforeEach() throws Exception {
baseCacheDir = tempDir.resolve("base");
ConfigurationCopy acuConf = new ConfigurationCopy(
- Map.of(CACHE_DIR_PROPERTY,
baseCacheDir.toAbsolutePath().toUri().toURL().toExternalForm()));
+ Map.of(CACHE_DIR_PROPERTY,
baseCacheDir.toAbsolutePath().toUri().toURL().toExternalForm(),
+ UPDATE_FAILURE_GRACE_PERIOD_MINS, "1", ALLOWED_URLS_PATTERN,
".*"));
FACTORY = new LocalCachingContextClassLoaderFactory();
FACTORY.init(() -> new ConfigurationImpl(acuConf));
}
+ @Test
+ public void testAllowedUrls() throws Exception {
+ // use a different factory than other tests; only allow file: URLs
+ ConfigurationCopy acuConf = new ConfigurationCopy(
+ Map.of(CACHE_DIR_PROPERTY,
baseCacheDir.toAbsolutePath().toUri().toURL().toExternalForm(),
+ ALLOWED_URLS_PATTERN, "file:.*"));
+ var factory = new LocalCachingContextClassLoaderFactory();
+ factory.init(() -> new ConfigurationImpl(acuConf));
+
+ // case 1: all URLs pass (normal case, covered by other tests)
+
+ // case 2: context definition URL fails to match the pattern
+ var ex = assertThrows(ContextClassLoaderException.class,
+ () -> factory.getClassLoader(hdfsAllContext.toExternalForm()));
+ assertTrue(ex.getCause() instanceof IllegalArgumentException);
+ assertTrue(ex.getCause().getMessage().contains("Context definition
location (hdfs:"));
+
+ // case 3a: context definition URL matches, but resource URL should fail
to match the pattern,
+ // but it works anyway, because the resources were downloaded already by a
different instance
+ // (in this case, by a less restrictive FACTORY instance) and no new
connection is made
+ FACTORY.getClassLoader(hdfsAllContext.toExternalForm());
+ factory.getClassLoader(localAllContext.toExternalForm()); // same resources
+
+ // case 3b: context definition URL matches, but resource URL fails to
match the pattern
+ // in this case, we use a new context definition, with a resource that
doesn't exist locally
+ var newResources = new LinkedHashSet<Resource>();
+ var badUrl = "http://localhost/some/path";
+ newResources.add(new Resource(new URL(badUrl), "MD5", BAD_MD5));
+ var context2 = new ContextDefinition(MONITOR_INTERVAL_SECS, newResources);
+ var disallowedContext =
tempDir.resolve("context-with-disallowed-resource-url.json");
+ Files.writeString(disallowedContext, context2.toJson(),
StandardOpenOption.CREATE,
+ StandardOpenOption.TRUNCATE_EXISTING);
+ ex = assertThrows(ContextClassLoaderException.class,
+ () ->
factory.getClassLoader(disallowedContext.toUri().toURL().toExternalForm()));
+ assertTrue(ex.getCause() instanceof IllegalStateException);
+ assertTrue(ex.getCause().getCause() instanceof ExecutionException);
+ assertTrue(ex.getCause().getCause().getCause() instanceof
IllegalArgumentException);
+ assertTrue(ex.getCause().getCause().getCause().getMessage().contains(
+ "Resource location (" + badUrl + ")"),
ex.getCause().getCause().getCause()::getMessage);
+ }
+
@Test
public void testCreateFromLocal() throws Exception {
final ClassLoader cl = FACTORY.getClassLoader(localAllContext.toString());
@@ -336,7 +379,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
ex.getCause().getCause().getCause()::getMessage);
assertTrue(
ex.getCause().getCause().getCause().getMessage()
- .endsWith("TestA.jar does not match checksum in context definition
1234"),
+ .endsWith("TestA.jar does not match checksum in context definition
" + BAD_MD5),
ex.getCause().getCause().getCause()::getMessage);
}
@@ -609,17 +652,17 @@ public class LocalCachingContextClassLoaderFactoryTest {
testClassLoads(cl, classC);
testClassLoads(cl, classD);
- final List<URL> masterList = new ArrayList<>();
- masterList.add(jarAOrigLocation);
- masterList.add(jarBOrigLocation);
- masterList.add(jarCOrigLocation);
- masterList.add(jarDOrigLocation);
+ final List<URL> allList = new ArrayList<>();
+ allList.add(jarAOrigLocation);
+ allList.add(jarBOrigLocation);
+ allList.add(jarCOrigLocation);
+ allList.add(jarDOrigLocation);
- List<URL> priorList = masterList;
+ List<URL> priorList = allList;
ClassLoader priorCL = cl;
for (int i = 0; i < 20; i++) {
- final List<URL> updatedList = new ArrayList<>(masterList);
+ final List<URL> updatedList = new ArrayList<>(allList);
Collections.shuffle(updatedList);
final URL removed = updatedList.remove(0);
@@ -669,20 +712,12 @@ public class LocalCachingContextClassLoaderFactoryTest {
@Test
public void testGracePeriod() throws Exception {
- final LocalCachingContextClassLoaderFactory localFactory =
- new LocalCachingContextClassLoaderFactory();
-
- String baseCacheDir = tempDir.resolve("base").toUri().toString();
- ConfigurationCopy acuConf = new ConfigurationCopy(
- Map.of(CACHE_DIR_PROPERTY, baseCacheDir,
UPDATE_FAILURE_GRACE_PERIOD_MINS, "1"));
- localFactory.init(() -> new ConfigurationImpl(acuConf));
-
final var def = ContextDefinition.create(MONITOR_INTERVAL_SECS, "SHA-512",
jarAOrigLocation);
final var defFilePath =
createContextDefinitionFile(fs, "UpdateNonExistentResource.json",
def.toJson());
final URL updateDefUrl = new URL(fs.getUri().toString() +
defFilePath.toUri().toString());
- final ClassLoader cl =
localFactory.getClassLoader(updateDefUrl.toString());
+ final ClassLoader cl = FACTORY.getClassLoader(updateDefUrl.toString());
testClassLoads(cl, classA);
testClassFailsToLoad(cl, classB);
@@ -708,7 +743,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
// wait 2x the monitor interval
Thread.sleep(MONITOR_INTERVAL_SECS * 2 * 1000);
- final ClassLoader cl2 =
localFactory.getClassLoader(updateDefUrl.toString());
+ final ClassLoader cl2 = FACTORY.getClassLoader(updateDefUrl.toString());
// validate that the classloader has not updated
assertEquals(cl, cl2);
@@ -721,7 +756,7 @@ public class LocalCachingContextClassLoaderFactoryTest {
Thread.sleep(120_000);
var ex = assertThrows(ContextClassLoaderException.class,
- () -> localFactory.getClassLoader(updateDefUrl.toString()));
+ () -> FACTORY.getClassLoader(updateDefUrl.toString()));
boolean foundExpectedException = false;
var cause = ex.getCause();
do {
diff --git
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
index 8ebad35..75b4d95 100644
---
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
+++
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/MiniAccumuloClusterClassLoaderFactoryTest.java
@@ -22,6 +22,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
+import static
org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory.ALLOWED_URLS_PATTERN;
import static
org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory.CACHE_DIR_PROPERTY;
import static
org.apache.accumulo.classloader.lcc.LocalCachingContextClassLoaderFactory.UPDATE_FAILURE_GRACE_PERIOD_MINS;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -112,6 +113,7 @@ public class MiniAccumuloClusterClassLoaderFactoryTest
extends SharedMiniCluster
cfg.setProperty(Property.GENERAL_CONTEXT_CLASSLOADER_FACTORY.getKey(),
LocalCachingContextClassLoaderFactory.class.getName());
cfg.setProperty(CACHE_DIR_PROPERTY,
tempDir.resolve("base").toUri().toString());
+ cfg.setProperty(ALLOWED_URLS_PATTERN, ".*");
cfg.setProperty(UPDATE_FAILURE_GRACE_PERIOD_MINS, "1");
}
}
diff --git
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
index 3d637ab..74408fb 100644
---
a/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
+++
b/modules/local-caching-classloader/src/test/java/org/apache/accumulo/classloader/lcc/util/LocalStoreTest.java
@@ -34,6 +34,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.LinkedHashSet;
+import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import org.apache.accumulo.classloader.lcc.TestUtils;
@@ -54,6 +55,9 @@ public class LocalStoreTest {
@TempDir
private static Path tempDir;
+ // a mock URL checker that allows all for test
+ private static final BiConsumer<String,URL> ALLOW_ALL_URLS = (type, url) ->
{};
+
private static final int MONITOR_INTERVAL_SECS = 5;
private static MiniDFSCluster hdfs;
private static Server jetty;
@@ -128,13 +132,16 @@ public class LocalStoreTest {
@Test
public void testPropertyNotSet() {
- assertThrows(NullPointerException.class, () -> new LocalStore(null));
+ // test baseDir not set
+ assertThrows(NullPointerException.class, () -> new LocalStore(null,
ALLOW_ALL_URLS));
+ // test URL checker not set
+ assertThrows(NullPointerException.class, () -> new
LocalStore(baseCacheDir, null));
}
@Test
public void testCreateBaseDirs() throws Exception {
assertFalse(Files.exists(baseCacheDir));
- var localStore = new LocalStore(baseCacheDir);
+ var localStore = new LocalStore(baseCacheDir, ALLOW_ALL_URLS);
assertTrue(Files.exists(baseCacheDir));
assertTrue(Files.exists(baseCacheDir.resolve("contexts")));
assertTrue(Files.exists(baseCacheDir.resolve("resources")));
@@ -145,10 +152,10 @@ public class LocalStoreTest {
@Test
public void testCreateBaseDirsMultipleTimes() throws Exception {
assertFalse(Files.exists(baseCacheDir));
- assertNotNull(new LocalStore(baseCacheDir));
- assertNotNull(new LocalStore(baseCacheDir));
- assertNotNull(new LocalStore(baseCacheDir));
- assertNotNull(new LocalStore(baseCacheDir));
+ assertNotNull(new LocalStore(baseCacheDir, ALLOW_ALL_URLS));
+ assertNotNull(new LocalStore(baseCacheDir, ALLOW_ALL_URLS));
+ assertNotNull(new LocalStore(baseCacheDir, ALLOW_ALL_URLS));
+ assertNotNull(new LocalStore(baseCacheDir, ALLOW_ALL_URLS));
assertTrue(Files.exists(baseCacheDir));
}
@@ -213,7 +220,7 @@ public class LocalStoreTest {
@Test
public void testStoreContextResources() throws Exception {
- var localStore = new LocalStore(baseCacheDir);
+ var localStore = new LocalStore(baseCacheDir, ALLOW_ALL_URLS);
localStore.storeContextResources(def);
// Confirm the 3 jars are cached locally
@@ -227,7 +234,7 @@ public class LocalStoreTest {
@Test
public void testClassLoader() throws Exception {
- var urls = new LocalStore(baseCacheDir).storeContextResources(def);
+ var urls = new LocalStore(baseCacheDir,
ALLOW_ALL_URLS).storeContextResources(def);
var contextClassLoader = LccUtils.createClassLoader("url", urls);
testClassLoads(contextClassLoader, classA);
@@ -237,7 +244,7 @@ public class LocalStoreTest {
@Test
public void testClassLoaderUpdate() throws Exception {
- var localStore = new LocalStore(baseCacheDir);
+ var localStore = new LocalStore(baseCacheDir, ALLOW_ALL_URLS);
var urls = localStore.storeContextResources(def);
final var contextClassLoader = LccUtils.createClassLoader("url", urls);