diff --git a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy index 4780da0a60e..9afbd436400 100644 --- a/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy +++ b/buildSrc/src/main/groovy/org/elasticsearch/gradle/BuildPlugin.groovy @@ -18,7 +18,6 @@ */ package org.elasticsearch.gradle - import com.github.jengelman.gradle.plugins.shadow.ShadowPlugin import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import groovy.transform.CompileDynamic @@ -48,7 +47,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 @@ -408,11 +406,11 @@ class BuildPlugin implements Plugin { 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 @@ -452,9 +450,15 @@ class BuildPlugin implements Plugin { } } - 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) } } diff --git a/buildSrc/src/test/groovy/org/elasticsearch/gradle/BuildPluginTests.java b/buildSrc/src/test/groovy/org/elasticsearch/gradle/BuildPluginTests.java index 90af9a2401a..c61a0a39358 100644 --- a/buildSrc/src/test/groovy/org/elasticsearch/gradle/BuildPluginTests.java +++ b/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); + } + } diff --git a/buildSrc/src/test/java/org/elasticsearch/gradle/BuildPluginIT.java b/buildSrc/src/test/java/org/elasticsearch/gradle/BuildPluginIT.java index dd0dbb25208..2e0e594b0f5 100644 --- a/buildSrc/src/test/java/org/elasticsearch/gradle/BuildPluginIT.java +++ b/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 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 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 lines) throws IOException { + final File projectDir = getProjectDir("elasticsearch.build"); + FileUtils.copyDirectory(projectDir, tmpDir.getRoot(), pathname -> pathname.getPath().contains("/build/") == false); + final List 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())