diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d3d9c51..9b451fe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ * Added fallback to binary mode on failure in zip digest computation +* Added support for user defined host whitelist from system property + ## 1.8.7 - May 24, 2022 * Paths in classpath are specified relative to appdir to avoid excessively long command lines. diff --git a/core/src/main/java/io/github/bekoenig/getdown/data/Build.java.tmpl b/core/src/main/java/io/github/bekoenig/getdown/data/Build.java.tmpl index 46996d98..6e9f57ac 100644 --- a/core/src/main/java/io/github/bekoenig/getdown/data/Build.java.tmpl +++ b/core/src/main/java/io/github/bekoenig/getdown/data/Build.java.tmpl @@ -5,11 +5,6 @@ package io.github.bekoenig.getdown.data; -import java.util.Arrays; -import java.util.List; - -import io.github.bekoenig.getdown.util.StringUtil; - /** * Contains static data provided during the build process. */ @@ -26,7 +21,7 @@ public class Build { } /** - *

The hosts which Getdown is allowed to communicate with. An empty list indicates that + *

The hosts which Getdown is allowed to communicate with. An empty string indicates that * no whitelist is configured and there are no limitations. By default, no host whitelist * is added to the binary, so it can be used to download and run applications from any * server. @@ -37,7 +32,7 @@ public class Build { * (e.g. {@code *.mycompany.com}) and multiple values can be separated by commas * (e.g. {@code app1.foo.com,app2.bar.com,app3.baz.com}). */ - public static List hostWhitelist () { - return Arrays.asList(StringUtil.parseStringArray("@host_whitelist@")); + public static String hostWhitelist () { + return "@host_whitelist@"; } } diff --git a/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java b/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java index 161a49d0..eb27390d 100644 --- a/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java +++ b/core/src/main/java/io/github/bekoenig/getdown/data/SysProps.java @@ -175,6 +175,13 @@ public static int threadPoolSize() { return Integer.getInteger("thread_pool_size", defaultSize); } + /** + * Returns the host whitelist from system property. + */ + public static String hostWhitelist() { + return System.getProperty("getdown.host.whitelist", ""); + } + /** * Parses a Java version system property using the supplied regular expression. The numbers * extracted from the regexp will be placed in each consecutive hundreds position in the diff --git a/core/src/main/java/io/github/bekoenig/getdown/util/HostWhitelist.java b/core/src/main/java/io/github/bekoenig/getdown/util/HostWhitelist.java index d37c34f2..c2e3bb24 100644 --- a/core/src/main/java/io/github/bekoenig/getdown/util/HostWhitelist.java +++ b/core/src/main/java/io/github/bekoenig/getdown/util/HostWhitelist.java @@ -6,24 +6,44 @@ package io.github.bekoenig.getdown.util; import io.github.bekoenig.getdown.data.Build; +import io.github.bekoenig.getdown.data.SysProps; import java.net.MalformedURLException; import java.net.URL; +import java.util.Arrays; import java.util.List; /** - * Optional support for compiling a URL host whitelist into the Getdown JAR. + * Optional support for compiling a URL host whitelist into the Getdown JAR or defined by system + * property. * Useful if you're on the paranoid end of the security spectrum. * * @see Build#hostWhitelist() + * @see SysProps#hostWhitelist() */ public final class HostWhitelist { + + /** + * Returns the active host whitelist. If no host whitelist was set in the build (default + * behavior), the system property with the same name is used. + */ + private static List activeHostWhitelist() { + // The compiled host whitelist has the highest priority. + String hostWhitelist = Build.hostWhitelist(); + // If the compiled host whitelist is blank, the system property can be used. + if (StringUtil.isBlank(hostWhitelist)) { + hostWhitelist = SysProps.hostWhitelist(); + } + + return Arrays.asList(StringUtil.parseStringArray(hostWhitelist)); + } + /** * Verifies that the specified URL should be accessible, per the built-in host whitelist. * See {@link Build#hostWhitelist()} and {@link #verify(List, URL)}. */ public static URL verify(URL url) throws MalformedURLException { - return verify(Build.hostWhitelist(), url); + return verify(activeHostWhitelist(), url); } /** diff --git a/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java b/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java index 67d6287a..43bf6647 100644 --- a/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java +++ b/core/src/test/java/io/github/bekoenig/getdown/data/SysPropsTest.java @@ -7,7 +7,10 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; +import org.junitpioneer.jupiter.ClearSystemProperty; +import org.junitpioneer.jupiter.SetSystemProperty; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; class SysPropsTest { @@ -66,4 +69,29 @@ void testAppbaseOverride() { assertEquals("https://barbaz.com/newapp", SysProps.overrideAppbase(appbase)); } } + + @Test + @ClearSystemProperty(key = "getdown.host.whitelist") + void test_hostWhitelist_undefined() { + // GIVEN + + // WHEN + String hostWhitelist = SysProps.hostWhitelist(); + + // THEN + assertThat(hostWhitelist).isEqualTo(""); + } + + @Test + @SetSystemProperty(key = "getdown.host.whitelist", value = "app1.foo.com,app2.bar.com,app3.baz.com") + void test_hostWhitelist_defined() { + // GIVEN + + // WHEN + String hostWhitelist = SysProps.hostWhitelist(); + + // THEN + assertThat(hostWhitelist).isEqualTo("app1.foo.com,app2.bar.com,app3.baz.com"); + } + }