Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
Expand Down Expand Up @@ -329,10 +330,31 @@ private Path download(InstallablePlugin plugin, Path tmpDir) throws Exception {
}
throw new UserException(ExitCodes.USAGE, msg);
}

verifyLocationNotInPluginsDirectory(pluginLocation);

terminal.println(logPrefix + "Downloading " + URLDecoder.decode(pluginLocation, StandardCharsets.UTF_8));
return downloadZip(pluginLocation, tmpDir);
}

@SuppressForbidden(reason = "Need to use Paths#get")
private void verifyLocationNotInPluginsDirectory(String pluginLocation) throws URISyntaxException, IOException, UserException {
if (pluginLocation == null) {
return;
}
URI uri = new URI(pluginLocation);
if ("file".equalsIgnoreCase(uri.getScheme())) {
Path pluginRealPath = Paths.get(uri).toRealPath();
Path pluginsDirectory = env.pluginsDir().toRealPath();
if (pluginRealPath.startsWith(pluginsDirectory)) {
throw new UserException(
ExitCodes.USAGE,
"plugin location [" + pluginLocation + "] is inside the plugins directory [" + pluginsDirectory + "]"
);
}
}
}

@SuppressForbidden(reason = "Need to use PathUtils#get")
private Path getPluginArchivePath(String pluginId, String pluginArchiveDir) throws UserException {
final Path path = PathUtils.get(pluginArchiveDir);
Expand Down Expand Up @@ -462,9 +484,9 @@ private static List<String> checkMisspelledPlugin(String pluginId) {
/** Downloads a zip from the url, into a temp file under the given temp dir. */
// pkg private for tests
@SuppressForbidden(reason = "We use getInputStream to download plugins")
Path downloadZip(String urlString, Path tmpDir) throws IOException {
Path downloadZip(String urlString, Path tmpDir) throws IOException, URISyntaxException {
terminal.println(VERBOSE, "Retrieving zip from " + urlString);
URL url = new URL(urlString);
URL url = new URI(urlString).toURL();
Path zip = Files.createTempFile(tmpDir, null, ".zip");
URLConnection urlConnection = this.proxy == null ? url.openConnection() : url.openConnection(this.proxy);
urlConnection.addRequestProperty("User-Agent", "elasticsearch-plugin-installer");
Expand Down Expand Up @@ -548,9 +570,10 @@ private InputStream urlOpenStream(final URL url) throws IOException {
* @throws IOException if an I/O exception occurs download or reading files and resources
* @throws PGPException if an exception occurs verifying the downloaded ZIP signature
* @throws UserException if checksum validation fails
* @throws URISyntaxException is the url is invalid
*/
private Path downloadAndValidate(final String urlString, final Path tmpDir, final boolean officialPlugin) throws IOException,
PGPException, UserException {
PGPException, UserException, URISyntaxException {
Path zip = downloadZip(urlString, tmpDir);
pathsToDeleteOnShutdown.add(zip);
String checksumUrlString = urlString + ".sha512";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,18 @@
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.GroupPrincipal;
Expand Down Expand Up @@ -552,8 +552,8 @@ public void testTransaction() throws Exception {
pluginZip.getId() + "-does-not-exist",
pluginZip.getLocation() + "-does-not-exist"
);
final FileNotFoundException e = expectThrows(
FileNotFoundException.class,
final NoSuchFileException e = expectThrows(
NoSuchFileException.class,
() -> installPlugins(List.of(pluginZip, nonexistentPluginZip), env.v1())
);
assertThat(e.getMessage(), containsString("does-not-exist"));
Expand Down Expand Up @@ -586,11 +586,24 @@ public void testSpaceInUrl() throws Exception {
assertPlugin("fake", pluginDir, env.v2());
}

public void testInstallFromInsidePluginsDirectory() throws Exception {
InstallablePlugin pluginZip = createPluginZip("fake", pluginDir);
Path pluginZipInsidePlugins = env.v2().pluginsDir().resolve("fake.zip");
try (InputStream in = FileSystemUtils.openFileURLStream(new URL(pluginZip.getLocation()))) {
Files.copy(in, pluginZipInsidePlugins, StandardCopyOption.REPLACE_EXISTING);
}
String location = pluginZipInsidePlugins.toUri().toURL().toString();
assumeTrue("requires file URL scheme", location.startsWith("file:"));
InstallablePlugin modifiedPlugin = new InstallablePlugin("fake", location);
UserException e = expectThrows(UserException.class, () -> installPlugin(modifiedPlugin));
assertThat(e.getMessage(), startsWith("plugin location [" + location + "] is inside the plugins directory"));
}

public void testMalformedUrlNotMaven() {
// has two colons, so it appears similar to maven coordinates
InstallablePlugin plugin = new InstallablePlugin("fake", "://host:1234");
MalformedURLException e = expectThrows(MalformedURLException.class, () -> installPlugin(plugin));
assertThat(e.getMessage(), containsString("no protocol"));
URISyntaxException e = expectThrows(URISyntaxException.class, () -> installPlugin(plugin));
assertThat(e.getMessage(), containsString("Expected scheme name"));
}

public void testFileNotMaven() {
Expand Down
6 changes: 6 additions & 0 deletions docs/changelog/137398.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 137398
summary: Error if installed plugin is inside plugins folder
area: Infra/Plugins
type: enhancement
issues:
- 27401