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.
This commit is contained in:
Jason Tedor 2019-08-26 09:37:25 -04:00
parent 767f648f8e
commit 9672ff388a
No known key found for this signature in database
GPG Key ID: FA89F05560F16BC5
3 changed files with 91 additions and 8 deletions

View File

@ -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> {
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<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)
}
}

View File

@ -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);
}
}

View File

@ -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())