|
@@ -19,12 +19,14 @@
|
|
|
|
|
|
package org.elasticsearch.repositories.uri;
|
|
|
|
|
|
-import com.google.common.collect.ImmutableList;
|
|
|
import org.elasticsearch.cluster.metadata.SnapshotId;
|
|
|
+import org.elasticsearch.common.Strings;
|
|
|
import org.elasticsearch.common.blobstore.BlobPath;
|
|
|
import org.elasticsearch.common.blobstore.BlobStore;
|
|
|
import org.elasticsearch.common.blobstore.url.URLBlobStore;
|
|
|
import org.elasticsearch.common.inject.Inject;
|
|
|
+import org.elasticsearch.common.util.URIPattern;
|
|
|
+import org.elasticsearch.env.Environment;
|
|
|
import org.elasticsearch.index.snapshots.IndexShardRepository;
|
|
|
import org.elasticsearch.repositories.RepositoryException;
|
|
|
import org.elasticsearch.repositories.RepositoryName;
|
|
@@ -32,6 +34,7 @@ import org.elasticsearch.repositories.RepositorySettings;
|
|
|
import org.elasticsearch.repositories.blobstore.BlobStoreRepository;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
+import java.net.URISyntaxException;
|
|
|
import java.net.URL;
|
|
|
import java.util.List;
|
|
|
|
|
@@ -48,6 +51,18 @@ public class URLRepository extends BlobStoreRepository {
|
|
|
|
|
|
public final static String TYPE = "url";
|
|
|
|
|
|
+ public final static String[] DEFAULT_SUPPORTED_PROTOCOLS = {"http", "https", "ftp", "file", "jar"};
|
|
|
+
|
|
|
+ public final static String SUPPORTED_PROTOCOLS_SETTING = "repositories.url.supported_protocols";
|
|
|
+
|
|
|
+ public final static String ALLOWED_URLS_SETTING = "repositories.url.allowed_urls";
|
|
|
+
|
|
|
+ private final String[] supportedProtocols;
|
|
|
+
|
|
|
+ private final URIPattern[] urlWhiteList;
|
|
|
+
|
|
|
+ private final Environment environment;
|
|
|
+
|
|
|
private final URLBlobStore blobStore;
|
|
|
|
|
|
private final BlobPath basePath;
|
|
@@ -63,17 +78,25 @@ public class URLRepository extends BlobStoreRepository {
|
|
|
* @throws IOException
|
|
|
*/
|
|
|
@Inject
|
|
|
- public URLRepository(RepositoryName name, RepositorySettings repositorySettings, IndexShardRepository indexShardRepository) throws IOException {
|
|
|
+ public URLRepository(RepositoryName name, RepositorySettings repositorySettings, IndexShardRepository indexShardRepository, Environment environment) throws IOException {
|
|
|
super(name.getName(), repositorySettings, indexShardRepository);
|
|
|
URL url;
|
|
|
- String path = repositorySettings.settings().get("url", settings.get("repositories.uri.url"));
|
|
|
+ String path = repositorySettings.settings().get("url", settings.get("repositories.url.url", settings.get("repositories.uri.url")));
|
|
|
if (path == null) {
|
|
|
throw new RepositoryException(name.name(), "missing url");
|
|
|
} else {
|
|
|
url = new URL(path);
|
|
|
}
|
|
|
+ supportedProtocols = settings.getAsArray(SUPPORTED_PROTOCOLS_SETTING, DEFAULT_SUPPORTED_PROTOCOLS);
|
|
|
+ String[] urlWhiteList = settings.getAsArray(ALLOWED_URLS_SETTING, Strings.EMPTY_ARRAY);
|
|
|
+ this.urlWhiteList = new URIPattern[urlWhiteList.length];
|
|
|
+ for (int i = 0; i < urlWhiteList.length; i++) {
|
|
|
+ this.urlWhiteList[i] = new URIPattern(urlWhiteList[i]);
|
|
|
+ }
|
|
|
+ this.environment = environment;
|
|
|
listDirectories = repositorySettings.settings().getAsBoolean("list_directories", settings.getAsBoolean("repositories.uri.list_directories", true));
|
|
|
- blobStore = new URLBlobStore(settings, url);
|
|
|
+ URL normalizedURL = checkURL(url);
|
|
|
+ blobStore = new URLBlobStore(settings, normalizedURL);
|
|
|
basePath = BlobPath.cleanPath();
|
|
|
}
|
|
|
|
|
@@ -114,4 +137,35 @@ public class URLRepository extends BlobStoreRepository {
|
|
|
throw new UnsupportedOperationException("shouldn't be called");
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Makes sure that the url is white listed or if it points to the local file system it matches one on of the root path in path.repo
|
|
|
+ */
|
|
|
+ private URL checkURL(URL url) {
|
|
|
+ String protocol = url.getProtocol();
|
|
|
+ if (protocol == null) {
|
|
|
+ throw new RepositoryException(repositoryName, "unknown url protocol from URL [" + url + "]");
|
|
|
+ }
|
|
|
+ for (String supportedProtocol : supportedProtocols) {
|
|
|
+ if (supportedProtocol.equals(protocol)) {
|
|
|
+ try {
|
|
|
+ if (URIPattern.match(urlWhiteList, url.toURI())) {
|
|
|
+ // URL matches white list - no additional processing is needed
|
|
|
+ return url;
|
|
|
+ }
|
|
|
+ } catch (URISyntaxException ex) {
|
|
|
+ logger.warn("cannot parse the specified url [{}]", url);
|
|
|
+ throw new RepositoryException(repositoryName, "cannot parse the specified url [" + url + "]");
|
|
|
+ }
|
|
|
+ // We didn't match white list - try to resolve against repo.path
|
|
|
+ URL normalizedUrl = environment.resolveRepoURL(url);
|
|
|
+ if (normalizedUrl == null) {
|
|
|
+ logger.warn("The specified url [{}] doesn't start with any repository paths specified by the path.repo setting: [{}] or by repositories.url.allowed_urls setting: [{}] ", url, environment.repoFiles());
|
|
|
+ throw new RepositoryException(repositoryName, "file url [" + url + "] doesn't match any of the locations specified by path.repo or repositories.url.allowed_urls");
|
|
|
+ }
|
|
|
+ return normalizedUrl;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new RepositoryException(repositoryName, "unsupported url protocol [" + protocol + "] from URL [" + url + "]");
|
|
|
+ }
|
|
|
+
|
|
|
}
|