This is an automated email from the ASF dual-hosted git repository.
joao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudstack.git
The following commit(s) were added to refs/heads/main by this push:
new ede39d8edc4 Configuration to disable URL validation when registering
templates/ISOs (#8751)
ede39d8edc4 is described below
commit ede39d8edc44ca05d4d2604fb27e996314c3db60
Author: Fabricio Duarte <[email protected]>
AuthorDate: Tue Aug 27 16:12:31 2024 -0300
Configuration to disable URL validation when registering templates/ISOs
(#8751)
---
.../java/com/cloud/template/TemplateManager.java | 9 +++++
.../cloud/template/HypervisorTemplateAdapter.java | 4 +-
.../com/cloud/template/TemplateManagerImpl.java | 2 +-
utils/src/main/java/com/cloud/utils/UriUtils.java | 45 ++++++++++++++++------
4 files changed, 45 insertions(+), 15 deletions(-)
diff --git
a/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java
b/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java
index 3b3537d5488..997ae3985f1 100644
---
a/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java
+++
b/engine/components-api/src/main/java/com/cloud/template/TemplateManager.java
@@ -51,6 +51,11 @@ public interface TemplateManager {
static final ConfigKey<Integer> TemplatePreloaderPoolSize = new
ConfigKey<Integer>("Advanced", Integer.class, TemplatePreloaderPoolSizeCK, "8",
"Size of the TemplateManager threadpool", false,
ConfigKey.Scope.Global);
+ ConfigKey<Boolean> ValidateUrlIsResolvableBeforeRegisteringTemplate = new
ConfigKey<>("Advanced", Boolean.class,
+ "validate.url.is.resolvable.before.registering.template", "true",
"Indicates whether CloudStack "
+ + "will validate if the provided URL is resolvable during the
register of templates/ISOs before persisting them in the database.",
+ true);
+
static final String VMWARE_TOOLS_ISO = "vmware-tools.iso";
static final String XS_TOOLS_ISO = "xs-tools.iso";
@@ -139,4 +144,8 @@ public interface TemplateManager {
TemplateType validateTemplateType(BaseCmd cmd, boolean isAdmin, boolean
isCrossZones);
List<DatadiskTO> getTemplateDisksOnImageStore(Long templateId,
DataStoreRole role, String configurationId);
+
+ static Boolean getValidateUrlIsResolvableBeforeRegisteringTemplateValue() {
+ return ValidateUrlIsResolvableBeforeRegisteringTemplate.value();
+ }
}
diff --git
a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java
b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java
index b7a511aad36..026a9350f33 100644
--- a/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java
+++ b/server/src/main/java/com/cloud/template/HypervisorTemplateAdapter.java
@@ -204,7 +204,7 @@ public class HypervisorTemplateAdapter extends
TemplateAdapterBase {
public TemplateProfile prepare(RegisterIsoCmd cmd) throws
ResourceAllocationException {
TemplateProfile profile = super.prepare(cmd);
String url = profile.getUrl();
- UriUtils.validateUrl(ImageFormat.ISO.getFileExtension(), url);
+ UriUtils.validateUrl(ImageFormat.ISO.getFileExtension(), url,
!TemplateManager.getValidateUrlIsResolvableBeforeRegisteringTemplateValue(),
false);
boolean followRedirects =
StorageManager.DataStoreDownloadFollowRedirects.value();
if (cmd.isDirectDownload()) {
DigestHelper.validateChecksumString(cmd.getChecksum());
@@ -238,7 +238,7 @@ public class HypervisorTemplateAdapter extends
TemplateAdapterBase {
public TemplateProfile prepare(RegisterTemplateCmd cmd) throws
ResourceAllocationException {
TemplateProfile profile = super.prepare(cmd);
String url = profile.getUrl();
- UriUtils.validateUrl(cmd.getFormat(), url, cmd.isDirectDownload());
+ UriUtils.validateUrl(cmd.getFormat(), url,
!TemplateManager.getValidateUrlIsResolvableBeforeRegisteringTemplateValue(),
cmd.isDirectDownload());
Hypervisor.HypervisorType hypervisor =
Hypervisor.HypervisorType.getType(cmd.getHypervisor());
boolean followRedirects =
StorageManager.DataStoreDownloadFollowRedirects.value();
if (cmd.isDirectDownload()) {
diff --git a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
index 4d095d09cc6..af558304981 100755
--- a/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/main/java/com/cloud/template/TemplateManagerImpl.java
@@ -2349,7 +2349,7 @@ public class TemplateManagerImpl extends ManagerBase
implements TemplateManager,
@Override
public ConfigKey<?>[] getConfigKeys() {
- return new ConfigKey<?>[] {AllowPublicUserTemplates,
TemplatePreloaderPoolSize};
+ return new ConfigKey<?>[] {AllowPublicUserTemplates,
TemplatePreloaderPoolSize, ValidateUrlIsResolvableBeforeRegisteringTemplate};
}
public List<TemplateAdapter> getTemplateAdapters() {
diff --git a/utils/src/main/java/com/cloud/utils/UriUtils.java
b/utils/src/main/java/com/cloud/utils/UriUtils.java
index e1766e691c2..4964215020d 100644
--- a/utils/src/main/java/com/cloud/utils/UriUtils.java
+++ b/utils/src/main/java/com/cloud/utils/UriUtils.java
@@ -263,10 +263,17 @@ public class UriUtils {
}
public static Pair<String, Integer> validateUrl(String format, String url)
throws IllegalArgumentException {
- return validateUrl(format, url, false);
+ return validateUrl(format, url, false, false);
}
- public static Pair<String, Integer> validateUrl(String format, String url,
boolean skipIpv6Check) throws IllegalArgumentException {
+ /**
+ * Verifies whether the provided URL is valid.
+ * @param skipHostCheck if false, this function will verify whether the
provided URL is resolvable, if it is a legal address and if it does not use
IPv6 (configured by `skipIpv6Check`). If any of these conditions are false, an
exception will be thrown.
+ * @param skipIpv6Check if false, this function will verify whether the
host uses IPv6 and, if it does, an exception will be thrown. This check is also
skipped if `skipHostCheck` is true.
+ * @return a pair containing the host and the corresponding port.
+ * @throws IllegalArgumentException if the provided URL is invalid.
+ */
+ public static Pair<String, Integer> validateUrl(String format, String url,
boolean skipHostCheck, boolean skipIpv6Check) throws IllegalArgumentException {
try {
URI uri = new URI(url);
if ((uri.getScheme() == null) ||
@@ -282,16 +289,8 @@ public class UriUtils {
}
String host = uri.getHost();
- try {
- InetAddress hostAddr = InetAddress.getByName(host);
- if (hostAddr.isAnyLocalAddress() ||
hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() ||
hostAddr.isMulticastAddress()) {
- throw new IllegalArgumentException("Illegal host specified
in url");
- }
- if (!skipIpv6Check && hostAddr instanceof Inet6Address) {
- throw new IllegalArgumentException("IPV6 addresses not
supported (" + hostAddr.getHostAddress() + ")");
- }
- } catch (UnknownHostException uhe) {
- throw new IllegalArgumentException("Unable to resolve " +
host);
+ if (!skipHostCheck) {
+ checkHost(host, skipIpv6Check);
}
// verify format
@@ -305,6 +304,28 @@ public class UriUtils {
}
}
+ /**
+ * Verifies whether the provided host is valid. Throws an
`IllegalArgumentException` if:
+ * <ul>
+ * <li>The host is not resolvable;</li>
+ * <li>The host address is illegal (any local, link local, loopback or
multicast address);</li>
+ * <li>The host uses IPv6. This check is skipped if `skipIv6Check` is
set to true.</li>
+ * </ul>
+ */
+ private static void checkHost(String host, boolean skipIpv6Check) {
+ try {
+ InetAddress hostAddr = InetAddress.getByName(host);
+ if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress()
|| hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress()) {
+ throw new IllegalArgumentException("Illegal host specified in
URL.");
+ }
+ if (!skipIpv6Check && hostAddr instanceof Inet6Address) {
+ throw new IllegalArgumentException(String.format("IPv6
addresses are not supported (%s).", hostAddr.getHostAddress()));
+ }
+ } catch (UnknownHostException uhe) {
+ throw new IllegalArgumentException(String.format("Unable to
resolve %s.", host));
+ }
+ }
+
/**
* Add element to priority list examining node attributes: priority (for
urls) and type (for checksums)
*/