Browse Source

Consider artifact repositories backed by S3 secure (#45950)

Since credentials are required to access such a repository, and these
repositories are accessed over an encrypted protocol (https), this
commit adds support to consider S3-backed artifact repositories as
secure. Additionally, we add tests for this functionality.
Jason Tedor 6 years ago
parent
commit
ebef8bf621

+ 13 - 10
buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy

@@ -48,7 +48,6 @@ import org.gradle.api.artifacts.ModuleVersionIdentifier
 import org.gradle.api.artifacts.ProjectDependency
 import org.gradle.api.artifacts.ResolvedArtifact
 import org.gradle.api.artifacts.dsl.RepositoryHandler
-import org.gradle.api.artifacts.repositories.ArtifactRepository
 import org.gradle.api.artifacts.repositories.IvyArtifactRepository
 import org.gradle.api.artifacts.repositories.IvyPatternRepositoryLayout
 import org.gradle.api.artifacts.repositories.MavenArtifactRepository
@@ -85,12 +84,10 @@ import org.gradle.util.GradleVersion
 
 import java.nio.charset.StandardCharsets
 import java.nio.file.Files
-import java.time.ZoneOffset
-import java.time.ZonedDateTime
 import java.util.regex.Matcher
 
-import static org.elasticsearch.gradle.tool.Boilerplate.maybeConfigure
 import static org.elasticsearch.gradle.tool.Boilerplate.findByName
+import static org.elasticsearch.gradle.tool.Boilerplate.maybeConfigure
 
 /**
  * Encapsulates build configuration for elasticsearch projects.
@@ -411,11 +408,11 @@ class BuildPlugin implements Plugin<Project> {
         project.getRepositories().all { repository ->
             if (repository instanceof MavenArtifactRepository) {
                 final MavenArtifactRepository maven = (MavenArtifactRepository) repository
-                assertRepositoryURIUsesHttps(maven, project, maven.getUrl())
-                repository.getArtifactUrls().each { uri -> assertRepositoryURIUsesHttps(maven, project, uri) }
+                assertRepositoryURIIsSecure(maven.name, project.path, maven.getUrl())
+                repository.getArtifactUrls().each { uri -> assertRepositoryURIIsSecure(maven.name, project.path, uri) }
             } else if (repository instanceof IvyArtifactRepository) {
                 final IvyArtifactRepository ivy = (IvyArtifactRepository) repository
-                assertRepositoryURIUsesHttps(ivy, project, ivy.getUrl())
+                assertRepositoryURIIsSecure(ivy.name, project.path, ivy.getUrl())
             }
         }
         RepositoryHandler repos = project.repositories
@@ -455,9 +452,15 @@ class BuildPlugin implements Plugin<Project> {
         }
     }
 
-    private static void assertRepositoryURIUsesHttps(final ArtifactRepository repository, final Project project, final URI uri) {
-        if (uri != null && uri.toURL().getProtocol().equals("http")) {
-            throw new GradleException("repository [${repository.name}] on project with path [${project.path}] is using http for artifacts on [${uri.toURL()}]")
+    static void assertRepositoryURIIsSecure(final String repositoryName, final String projectPath, final URI uri) {
+        if (uri != null && ["file", "https", "s3"].contains(uri.getScheme()) == false) {
+            final String message = String.format(
+                    Locale.ROOT,
+                    "repository [%s] on project with path [%s] is not using a secure protocol for artifacts on [%s]",
+                    repositoryName,
+                    projectPath,
+                    uri.toURL())
+            throw new GradleException(message)
         }
     }
 

+ 24 - 0
buildSrc/src/test/groovy/org/elasticsearch/gradle/BuildPluginTests.java

@@ -22,6 +22,9 @@ import org.elasticsearch.gradle.test.GradleUnitTestCase;
 import org.gradle.api.GradleException;
 import org.junit.Test;
 
+import java.net.URI;
+import java.net.URISyntaxException;
+
 
 public class BuildPluginTests extends GradleUnitTestCase {
 
@@ -36,4 +39,25 @@ public class BuildPluginTests extends GradleUnitTestCase {
         BuildPlugin.checkDockerVersionRecent("Docker version 17.04.0, build e68fc7a");
     }
 
+    @Test(expected = GradleException.class)
+    public void testRepositoryURIThatUsesHttpScheme() throws URISyntaxException {
+        final URI uri = new URI("http://s3.amazonaws.com/artifacts.elastic.co/maven");
+        BuildPlugin.assertRepositoryURIIsSecure("test", "test", uri);
+    }
+
+    public void testRepositoryThatUsesFileScheme() throws URISyntaxException {
+        final URI uri = new URI("file:/tmp/maven");
+        BuildPlugin.assertRepositoryURIIsSecure("test", "test", uri);
+    }
+
+    public void testRepositoryURIThatUsesHttpsScheme() throws URISyntaxException {
+        final URI uri = new URI("https://s3.amazonaws.com/artifacts.elastic.co/maven");
+        BuildPlugin.assertRepositoryURIIsSecure("test", "test", uri);
+    }
+
+    public void testRepositoryURIThatUsesS3Scheme() throws URISyntaxException {
+        final URI uri = new URI("s3://artifacts.elastic.co/maven");
+        BuildPlugin.assertRepositoryURIIsSecure("test", "test", uri);
+    }
+
 }

+ 55 - 0
buildSrc/src/test/java/org/elasticsearch/gradle/BuildPluginIT.java

@@ -18,19 +18,29 @@
  */
 package org.elasticsearch.gradle;
 
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.elasticsearch.gradle.test.GradleIntegrationTestCase;
 import org.gradle.testkit.runner.BuildResult;
+import org.gradle.testkit.runner.GradleRunner;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
 public class BuildPluginIT extends GradleIntegrationTestCase {
 
+    @Rule
+    public TemporaryFolder tmpDir = new TemporaryFolder();
+
     public void testPluginCanBeApplied() {
         BuildResult result = getGradleRunner("elasticsearch.build")
             .withArguments("hello", "-s")
@@ -46,6 +56,51 @@ public class BuildPluginIT extends GradleIntegrationTestCase {
         assertTaskSuccessful(result, ":check");
     }
 
+    public void testInsecureMavenRepository() throws IOException {
+        final String name = "elastic-maven";
+        final String url = "http://s3.amazonaws.com/artifacts.elastic.co/maven";
+        // add an insecure maven repository to the build.gradle
+        final List<String> lines = Arrays.asList(
+            "repositories {",
+            "  maven {",
+            "    name \"elastic-maven\"",
+            "    url \"" +  url + "\"\n",
+            "  }",
+            "}");
+        runInsecureArtifactRepositoryTest(name, url, lines);
+    }
+
+    public void testInsecureIvyRepository() throws IOException {
+        final String name = "elastic-ivy";
+        final String url = "http://s3.amazonaws.com/artifacts.elastic.co/ivy";
+        // add an insecure ivy repository to the build.gradle
+        final List<String> lines = Arrays.asList(
+            "repositories {",
+            "  ivy {",
+            "    name \"elastic-ivy\"",
+            "    url \"" +  url + "\"\n",
+            "  }",
+            "}");
+        runInsecureArtifactRepositoryTest(name, url, lines);
+    }
+
+    private void runInsecureArtifactRepositoryTest(final String name, final String url, final List<String> lines) throws IOException {
+        final File projectDir = getProjectDir("elasticsearch.build");
+        FileUtils.copyDirectory(projectDir, tmpDir.getRoot(), pathname -> pathname.getPath().contains("/build/") == false);
+        final List<String> buildGradleLines =
+            Files.readAllLines(tmpDir.getRoot().toPath().resolve("build.gradle"), StandardCharsets.UTF_8);
+        buildGradleLines.addAll(lines);
+        Files.write(tmpDir.getRoot().toPath().resolve("build.gradle"), buildGradleLines, StandardCharsets.UTF_8);
+        final BuildResult result = GradleRunner.create()
+            .withProjectDir(tmpDir.getRoot())
+            .withArguments("clean", "hello", "-s", "-i", "--warning-mode=all", "--scan")
+            .withPluginClasspath()
+            .buildAndFail();
+        assertOutputContains(
+            result.getOutput(),
+            "repository [" + name + "] on project with path [:] is not using a secure protocol for artifacts on [" + url + "]");
+    }
+
     public void testLicenseAndNotice() throws IOException {
         BuildResult result = getGradleRunner("elasticsearch.build")
             .withArguments("clean", "assemble", "-s", "-Dlocal.repo.path=" + getLocalTestRepoPath())