diff --git a/src/main/java/com/google/devtools/build/lib/BUILD b/src/main/java/com/google/devtools/build/lib/BUILD index b83d46330da715..360e98a6d57ce0 100644 --- a/src/main/java/com/google/devtools/build/lib/BUILD +++ b/src/main/java/com/google/devtools/build/lib/BUILD @@ -217,6 +217,19 @@ java_library( ], ) +java_library( + name = "runtime/command_line_path_factory", + srcs = [ + "runtime/CommandLinePathFactory.java", + ], + deps = [ + "//src/main/java/com/google/devtools/build/lib/analysis:blaze_directories", + "//src/main/java/com/google/devtools/build/lib/vfs", + "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment", + "//third_party:guava", + ], +) + java_library( name = "runtime", srcs = glob( @@ -229,6 +242,7 @@ java_library( "buildtool/BuildRequestOptions.java", "runtime/BlazeCommandResult.java", "runtime/CommandDispatcher.java", + "runtime/CommandLinePathFactory.java", "runtime/KeepGoingOption.java", "runtime/LoadingPhaseThreadsOption.java", ], @@ -239,6 +253,7 @@ java_library( ":loading-phase-threads-option", ":runtime/blaze_command_result", ":runtime/command_dispatcher", + ":runtime/command_line_path_factory", "//src/main/java/com/google/devtools/build/lib/actions", "//src/main/java/com/google/devtools/build/lib/actions:action_lookup_data", "//src/main/java/com/google/devtools/build/lib/actions:artifacts", diff --git a/src/main/java/com/google/devtools/build/lib/authandtls/BUILD b/src/main/java/com/google/devtools/build/lib/authandtls/BUILD index 906cd254e50fb6..252e6587c23c43 100644 --- a/src/main/java/com/google/devtools/build/lib/authandtls/BUILD +++ b/src/main/java/com/google/devtools/build/lib/authandtls/BUILD @@ -14,6 +14,8 @@ java_library( name = "authandtls", srcs = glob(["*.java"]), deps = [ + "//src/main/java/com/google/devtools/build/lib:runtime/command_line_path_factory", + "//src/main/java/com/google/devtools/build/lib/authandtls/credentialhelper", "//src/main/java/com/google/devtools/build/lib/concurrent", "//src/main/java/com/google/devtools/build/lib/events", "//src/main/java/com/google/devtools/build/lib/vfs", diff --git a/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java b/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java index 67e0d9e9195684..3d3ecac5bac70c 100644 --- a/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java +++ b/src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java @@ -19,8 +19,11 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperEnvironment; +import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperProvider; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.Reporter; +import com.google.devtools.build.lib.runtime.CommandLinePathFactory; import com.google.devtools.build.lib.vfs.FileSystem; import com.google.devtools.build.lib.vfs.Path; import io.grpc.CallCredentials; @@ -338,4 +341,27 @@ static Optional newCredentialsFromNetrc( "Failed to parse " + netrcFile.getPathString() + ": " + e.getMessage(), e); } } + + @VisibleForTesting + public static CredentialHelperProvider newCredentialHelperProvider( + CredentialHelperEnvironment environment, + CommandLinePathFactory pathFactory, + List helpers) + throws IOException { + Preconditions.checkNotNull(environment); + Preconditions.checkNotNull(pathFactory); + Preconditions.checkNotNull(helpers); + + CredentialHelperProvider.Builder builder = CredentialHelperProvider.builder(); + for (AuthAndTLSOptions.UnresolvedScopedCredentialHelper helper : helpers) { + Optional scope = helper.getScope(); + Path path = pathFactory.create(environment.getClientEnvironment(), helper.getPath()); + if (scope.isPresent()) { + builder.add(scope.get(), path); + } else { + builder.add(path); + } + } + return builder.build(); + } } diff --git a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java index b5c33b5d8ddb70..71da832ebd3afc 100644 --- a/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java +++ b/src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java @@ -19,7 +19,6 @@ import build.bazel.remote.execution.v2.DigestFunction; import build.bazel.remote.execution.v2.ServerCapabilities; import com.google.auth.Credentials; -import com.google.auto.value.AutoValue; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Ascii; import com.google.common.base.Preconditions; @@ -46,11 +45,8 @@ import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget; import com.google.devtools.build.lib.analysis.test.TestProvider; import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions; -import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions.UnresolvedScopedCredentialHelper; import com.google.devtools.build.lib.authandtls.CallCredentialsProvider; import com.google.devtools.build.lib.authandtls.GoogleAuthUtils; -import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperEnvironment; -import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperProvider; import com.google.devtools.build.lib.bazel.repository.downloader.Downloader; import com.google.devtools.build.lib.buildeventstream.BuildEventArtifactUploader; import com.google.devtools.build.lib.buildeventstream.LocalFilesArtifactUploader; @@ -79,7 +75,6 @@ import com.google.devtools.build.lib.runtime.BuildEventArtifactUploaderFactory; import com.google.devtools.build.lib.runtime.Command; import com.google.devtools.build.lib.runtime.CommandEnvironment; -import com.google.devtools.build.lib.runtime.CommandLinePathFactory; import com.google.devtools.build.lib.runtime.RepositoryRemoteExecutor; import com.google.devtools.build.lib.runtime.RepositoryRemoteExecutorFactory; import com.google.devtools.build.lib.runtime.ServerBuilder; @@ -1044,29 +1039,6 @@ RemoteActionContextProvider getActionContextProvider() { return actionContextProvider; } - @VisibleForTesting - static CredentialHelperProvider newCredentialHelperProvider( - CredentialHelperEnvironment environment, - CommandLinePathFactory pathFactory, - List helpers) - throws IOException { - Preconditions.checkNotNull(environment); - Preconditions.checkNotNull(pathFactory); - Preconditions.checkNotNull(helpers); - - CredentialHelperProvider.Builder builder = CredentialHelperProvider.builder(); - for (UnresolvedScopedCredentialHelper helper : helpers) { - Optional scope = helper.getScope(); - Path path = pathFactory.create(environment.getClientEnvironment(), helper.getPath()); - if (scope.isPresent()) { - builder.add(scope.get(), path); - } else { - builder.add(path); - } - } - return builder.build(); - } - static Credentials newCredentials( Map clientEnv, FileSystem fileSystem, @@ -1095,14 +1067,4 @@ static Credentials newCredentials( return credentials; } - - @VisibleForTesting - @AutoValue - abstract static class ScopedCredentialHelper { - /** Returns the scope of the credential helper (if any). */ - public abstract Optional getScope(); - - /** Returns the path of the credential helper. */ - public abstract Path getPath(); - } } diff --git a/src/test/java/com/google/devtools/build/lib/BUILD b/src/test/java/com/google/devtools/build/lib/BUILD index 8c6f153c7296df..d61b60c5b2f045 100644 --- a/src/test/java/com/google/devtools/build/lib/BUILD +++ b/src/test/java/com/google/devtools/build/lib/BUILD @@ -126,6 +126,7 @@ java_test( "//src/main/java/com/google/devtools/build/lib:runtime", "//src/main/java/com/google/devtools/build/lib:runtime/blaze_command_result", "//src/main/java/com/google/devtools/build/lib:runtime/command_dispatcher", + "//src/main/java/com/google/devtools/build/lib:runtime/command_line_path_factory", "//src/main/java/com/google/devtools/build/lib:runtime/safe_request_logging", "//src/main/java/com/google/devtools/build/lib/actions", "//src/main/java/com/google/devtools/build/lib/actions:action_lookup_data", diff --git a/src/test/java/com/google/devtools/build/lib/authandtls/BUILD b/src/test/java/com/google/devtools/build/lib/authandtls/BUILD index 15b1981f93b8a4..ae8cd09431e06c 100644 --- a/src/test/java/com/google/devtools/build/lib/authandtls/BUILD +++ b/src/test/java/com/google/devtools/build/lib/authandtls/BUILD @@ -24,7 +24,10 @@ java_library( ], ), deps = [ + "//src/main/java/com/google/devtools/build/lib:runtime/command_line_path_factory", "//src/main/java/com/google/devtools/build/lib/authandtls", + "//src/main/java/com/google/devtools/build/lib/authandtls/credentialhelper", + "//src/main/java/com/google/devtools/build/lib/events", "//src/main/java/com/google/devtools/build/lib/vfs", "//src/main/java/com/google/devtools/build/lib/vfs/inmemoryfs", "//src/main/java/com/google/devtools/common/options", diff --git a/src/test/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtilsTest.java b/src/test/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtilsTest.java index a3dc50273d82ae..0fb1d69e2cebcd 100644 --- a/src/test/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtilsTest.java +++ b/src/test/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtilsTest.java @@ -19,13 +19,25 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.auth.Credentials; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; +import com.google.common.eventbus.EventBus; +import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperEnvironment; +import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperProvider; +import com.google.devtools.build.lib.events.Reporter; +import com.google.devtools.build.lib.runtime.CommandLinePathFactory; import com.google.devtools.build.lib.testutil.Scratch; import com.google.devtools.build.lib.vfs.DigestHashFunction; import com.google.devtools.build.lib.vfs.FileSystem; +import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem; +import com.google.devtools.common.options.OptionsParsingException; +import java.io.IOException; +import java.io.OutputStream; import java.net.URI; +import java.time.Duration; import java.util.List; import java.util.Map; import java.util.Optional; @@ -102,10 +114,264 @@ public void testNetrc_netrcFromNetrcEnvNotExist_shouldIgnore() throws Exception assertThat(GoogleAuthUtils.newCredentialsFromNetrc(clientEnv, fileSystem)).isEmpty(); } + @Test + public void testCredentialHelperProvider() throws Exception { + FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256); + + Path workspace = fileSystem.getPath("/workspace"); + Path pathValue = fileSystem.getPath("/usr/local/bin"); + pathValue.createDirectoryAndParents(); + + CredentialHelperEnvironment credentialHelperEnvironment = + CredentialHelperEnvironment.newBuilder() + .setEventReporter(new Reporter(new EventBus())) + .setWorkspacePath(workspace) + .setClientEnvironment(ImmutableMap.of("PATH", pathValue.getPathString())) + .setHelperExecutionTimeout(Duration.ZERO) + .build(); + CommandLinePathFactory commandLinePathFactory = + new CommandLinePathFactory(fileSystem, ImmutableMap.of("workspace", workspace)); + + Path unusedHelper = createExecutable(fileSystem, "/unused/helper"); + + Path defaultHelper = createExecutable(fileSystem, "/default/helper"); + Path exampleComHelper = createExecutable(fileSystem, "/example/com/helper"); + Path fooExampleComHelper = createExecutable(fileSystem, "/foo/example/com/helper"); + Path exampleComWildcardHelper = createExecutable(fileSystem, "/example/com/wildcard/helper"); + + Path exampleOrgHelper = createExecutable(workspace.getRelative("helpers/example-org")); + + // No helpers. + CredentialHelperProvider credentialHelperProvider1 = + newCredentialHelperProvider( + credentialHelperEnvironment, commandLinePathFactory, ImmutableList.of()); + assertThat(credentialHelperProvider1.findCredentialHelper(URI.create("https://example.com"))) + .isEmpty(); + assertThat( + credentialHelperProvider1.findCredentialHelper(URI.create("https://foo.example.com"))) + .isEmpty(); + + // Default helper only. + CredentialHelperProvider credentialHelperProvider2 = + newCredentialHelperProvider( + credentialHelperEnvironment, + commandLinePathFactory, + ImmutableList.of(defaultHelper.getPathString())); + assertThat( + credentialHelperProvider2 + .findCredentialHelper(URI.create("https://example.com")) + .get() + .getPath()) + .isEqualTo(defaultHelper); + assertThat( + credentialHelperProvider2 + .findCredentialHelper(URI.create("https://foo.example.com")) + .get() + .getPath()) + .isEqualTo(defaultHelper); + + // Default and exact match. + CredentialHelperProvider credentialHelperProvider3 = + newCredentialHelperProvider( + credentialHelperEnvironment, + commandLinePathFactory, + ImmutableList.of( + defaultHelper.getPathString(), "example.com=" + exampleComHelper.getPathString())); + assertThat( + credentialHelperProvider3 + .findCredentialHelper(URI.create("https://example.com")) + .get() + .getPath()) + .isEqualTo(exampleComHelper); + assertThat( + credentialHelperProvider3 + .findCredentialHelper(URI.create("https://foo.example.com")) + .get() + .getPath()) + .isEqualTo(defaultHelper); + + // Exact match without default. + CredentialHelperProvider credentialHelperProvider4 = + newCredentialHelperProvider( + credentialHelperEnvironment, + commandLinePathFactory, + ImmutableList.of("example.com=" + exampleComHelper.getPathString())); + assertThat( + credentialHelperProvider4 + .findCredentialHelper(URI.create("https://example.com")) + .get() + .getPath()) + .isEqualTo(exampleComHelper); + assertThat( + credentialHelperProvider4.findCredentialHelper(URI.create("https://foo.example.com"))) + .isEmpty(); + + // Multiple scoped helpers with default. + CredentialHelperProvider credentialHelperProvider5 = + newCredentialHelperProvider( + credentialHelperEnvironment, + commandLinePathFactory, + ImmutableList.of( + defaultHelper.getPathString(), + "example.com=" + exampleComHelper.getPathString(), + "*.foo.example.com=" + fooExampleComHelper.getPathString(), + "*.example.com=" + exampleComWildcardHelper.getPathString(), + "example.org=%workspace%/helpers/example-org")); + assertThat( + credentialHelperProvider5 + .findCredentialHelper(URI.create("https://anotherdomain.com")) + .get() + .getPath()) + .isEqualTo(defaultHelper); + assertThat( + credentialHelperProvider5 + .findCredentialHelper(URI.create("https://example.com")) + .get() + .getPath()) + .isEqualTo(exampleComHelper); + assertThat( + credentialHelperProvider5 + .findCredentialHelper(URI.create("https://foo.example.com")) + .get() + .getPath()) + .isEqualTo(fooExampleComHelper); + assertThat( + credentialHelperProvider5 + .findCredentialHelper(URI.create("https://abc.foo.example.com")) + .get() + .getPath()) + .isEqualTo(fooExampleComHelper); + assertThat( + credentialHelperProvider5 + .findCredentialHelper(URI.create("https://bar.example.com")) + .get() + .getPath()) + .isEqualTo(exampleComWildcardHelper); + assertThat( + credentialHelperProvider5 + .findCredentialHelper(URI.create("https://abc.bar.example.com")) + .get() + .getPath()) + .isEqualTo(exampleComWildcardHelper); + assertThat( + credentialHelperProvider5 + .findCredentialHelper(URI.create("https://example.org")) + .get() + .getPath()) + .isEqualTo(exampleOrgHelper); + + // Helpers override. + CredentialHelperProvider credentialHelperProvider6 = + newCredentialHelperProvider( + credentialHelperEnvironment, + commandLinePathFactory, + ImmutableList.of( + // + unusedHelper.getPathString(), + + // + defaultHelper.getPathString(), + "example.com=" + unusedHelper.getPathString(), + "*.example.com=" + unusedHelper.getPathString(), + "example.org=" + unusedHelper.getPathString(), + "*.example.org=" + exampleOrgHelper.getPathString(), + + // + "*.example.com=" + exampleComWildcardHelper.getPathString(), + "example.org=" + exampleOrgHelper.getPathString(), + "*.foo.example.com=" + unusedHelper.getPathString(), + + // + "example.com=" + exampleComHelper.getPathString(), + "*.foo.example.com=" + fooExampleComHelper.getPathString())); + assertThat( + credentialHelperProvider6 + .findCredentialHelper(URI.create("https://anotherdomain.com")) + .get() + .getPath()) + .isEqualTo(defaultHelper); + assertThat( + credentialHelperProvider6 + .findCredentialHelper(URI.create("https://example.com")) + .get() + .getPath()) + .isEqualTo(exampleComHelper); + assertThat( + credentialHelperProvider6 + .findCredentialHelper(URI.create("https://foo.example.com")) + .get() + .getPath()) + .isEqualTo(fooExampleComHelper); + assertThat( + credentialHelperProvider6 + .findCredentialHelper(URI.create("https://bar.example.com")) + .get() + .getPath()) + .isEqualTo(exampleComWildcardHelper); + assertThat( + credentialHelperProvider6 + .findCredentialHelper(URI.create("https://example.org")) + .get() + .getPath()) + .isEqualTo(exampleOrgHelper); + assertThat( + credentialHelperProvider6 + .findCredentialHelper(URI.create("https://foo.example.org")) + .get() + .getPath()) + .isEqualTo(exampleOrgHelper); + } + + private static Path createExecutable(FileSystem fileSystem, String path) throws IOException { + Preconditions.checkNotNull(fileSystem); + Preconditions.checkNotNull(path); + + return createExecutable(fileSystem.getPath(path)); + } + + private static Path createExecutable(Path path) throws IOException { + Preconditions.checkNotNull(path); + + path.getParentDirectory().createDirectoryAndParents(); + try (OutputStream unused = path.getOutputStream()) { + // Nothing to do. + } + path.setExecutable(true); + + return path; + } + private static void assertRequestMetadata( Map> requestMetadata, String username, String password) { assertThat(requestMetadata.keySet()).containsExactly("Authorization"); assertThat(Iterables.getOnlyElement(requestMetadata.values())) .containsExactly(BasicHttpAuthenticationEncoder.encode(username, password, UTF_8)); } + + private static CredentialHelperProvider newCredentialHelperProvider( + CredentialHelperEnvironment credentialHelperEnvironment, + CommandLinePathFactory commandLinePathFactory, + ImmutableList inputs) + throws Exception { + Preconditions.checkNotNull(credentialHelperEnvironment); + Preconditions.checkNotNull(commandLinePathFactory); + Preconditions.checkNotNull(inputs); + + return GoogleAuthUtils.newCredentialHelperProvider( + credentialHelperEnvironment, + commandLinePathFactory, + ImmutableList.copyOf( + Iterables.transform(inputs, s -> createUnresolvedScopedCredentialHelper(s)))); + } + + private static AuthAndTLSOptions.UnresolvedScopedCredentialHelper + createUnresolvedScopedCredentialHelper(String input) { + Preconditions.checkNotNull(input); + + try { + return AuthAndTLSOptions.UnresolvedScopedCredentialHelperConverter.INSTANCE.convert(input); + } catch (OptionsParsingException e) { + throw new IllegalStateException(e); + } + } } diff --git a/src/test/java/com/google/devtools/build/lib/remote/BUILD b/src/test/java/com/google/devtools/build/lib/remote/BUILD index 7a7e06d842e8e7..8c9d36091d68fc 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/BUILD +++ b/src/test/java/com/google/devtools/build/lib/remote/BUILD @@ -53,7 +53,6 @@ java_test( "//src/main/java/com/google/devtools/build/lib/analysis:config/core_options", "//src/main/java/com/google/devtools/build/lib/analysis:server_directories", "//src/main/java/com/google/devtools/build/lib/authandtls", - "//src/main/java/com/google/devtools/build/lib/authandtls/credentialhelper", "//src/main/java/com/google/devtools/build/lib/buildeventstream", "//src/main/java/com/google/devtools/build/lib/clock", "//src/main/java/com/google/devtools/build/lib/collect/nestedset", diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteModuleTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteModuleTest.java index 94479e9ad7544c..93ea38e8c389fb 100644 --- a/src/test/java/com/google/devtools/build/lib/remote/RemoteModuleTest.java +++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteModuleTest.java @@ -14,7 +14,6 @@ package com.google.devtools.build.lib.remote; import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth8.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -27,18 +26,13 @@ import build.bazel.remote.execution.v2.GetCapabilitiesRequest; import build.bazel.remote.execution.v2.ServerCapabilities; import com.google.auth.Credentials; -import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; import com.google.common.eventbus.EventBus; import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.analysis.ServerDirectories; import com.google.devtools.build.lib.analysis.config.CoreOptions; import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions; -import com.google.devtools.build.lib.authandtls.AuthAndTLSOptions.UnresolvedScopedCredentialHelper; -import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperEnvironment; -import com.google.devtools.build.lib.authandtls.credentialhelper.CredentialHelperProvider; import com.google.devtools.build.lib.events.Reporter; import com.google.devtools.build.lib.exec.BinTools; import com.google.devtools.build.lib.exec.ExecutionOptions; @@ -50,18 +44,15 @@ import com.google.devtools.build.lib.runtime.ClientOptions; import com.google.devtools.build.lib.runtime.Command; import com.google.devtools.build.lib.runtime.CommandEnvironment; -import com.google.devtools.build.lib.runtime.CommandLinePathFactory; import com.google.devtools.build.lib.runtime.CommonCommandOptions; import com.google.devtools.build.lib.runtime.commands.BuildCommand; import com.google.devtools.build.lib.testutil.Scratch; import com.google.devtools.build.lib.util.AbruptExitException; import com.google.devtools.build.lib.vfs.DigestHashFunction; import com.google.devtools.build.lib.vfs.FileSystem; -import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem; import com.google.devtools.common.options.Options; import com.google.devtools.common.options.OptionsParser; -import com.google.devtools.common.options.OptionsParsingException; import com.google.devtools.common.options.OptionsParsingResult; import io.grpc.BindableService; import io.grpc.Server; @@ -71,9 +62,7 @@ import io.grpc.stub.StreamObserver; import io.grpc.util.MutableHandlerRegistry; import java.io.IOException; -import java.io.OutputStream; import java.net.URI; -import java.time.Duration; import java.util.ArrayList; import java.util.Map; import org.junit.Test; @@ -505,258 +494,4 @@ public void testNetrc_netrcWithoutRemoteCache() throws Exception { assertThat(credentials.getRequestMetadata(URI.create("https://foo.example.org"))).isNotEmpty(); assertThat(credentials.getRequestMetadata(URI.create("https://bar.example.org"))).isEmpty(); } - - @Test - public void testCredentialHelperProvider() throws Exception { - FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256); - - Path workspace = fileSystem.getPath("/workspace"); - Path pathValue = fileSystem.getPath("/usr/local/bin"); - pathValue.createDirectoryAndParents(); - - CredentialHelperEnvironment credentialHelperEnvironment = - CredentialHelperEnvironment.newBuilder() - .setEventReporter(new Reporter(new EventBus())) - .setWorkspacePath(workspace) - .setClientEnvironment(ImmutableMap.of("PATH", pathValue.getPathString())) - .setHelperExecutionTimeout(Duration.ZERO) - .build(); - CommandLinePathFactory commandLinePathFactory = - new CommandLinePathFactory(fileSystem, ImmutableMap.of("workspace", workspace)); - - Path unusedHelper = createExecutable(fileSystem, "/unused/helper"); - - Path defaultHelper = createExecutable(fileSystem, "/default/helper"); - Path exampleComHelper = createExecutable(fileSystem, "/example/com/helper"); - Path fooExampleComHelper = createExecutable(fileSystem, "/foo/example/com/helper"); - Path exampleComWildcardHelper = createExecutable(fileSystem, "/example/com/wildcard/helper"); - - Path exampleOrgHelper = createExecutable(workspace.getRelative("helpers/example-org")); - - // No helpers. - CredentialHelperProvider credentialHelperProvider1 = - newCredentialHelperProvider( - credentialHelperEnvironment, commandLinePathFactory, ImmutableList.of()); - assertThat(credentialHelperProvider1.findCredentialHelper(URI.create("https://example.com"))) - .isEmpty(); - assertThat( - credentialHelperProvider1.findCredentialHelper(URI.create("https://foo.example.com"))) - .isEmpty(); - - // Default helper only. - CredentialHelperProvider credentialHelperProvider2 = - newCredentialHelperProvider( - credentialHelperEnvironment, - commandLinePathFactory, - ImmutableList.of(defaultHelper.getPathString())); - assertThat( - credentialHelperProvider2 - .findCredentialHelper(URI.create("https://example.com")) - .get() - .getPath()) - .isEqualTo(defaultHelper); - assertThat( - credentialHelperProvider2 - .findCredentialHelper(URI.create("https://foo.example.com")) - .get() - .getPath()) - .isEqualTo(defaultHelper); - - // Default and exact match. - CredentialHelperProvider credentialHelperProvider3 = - newCredentialHelperProvider( - credentialHelperEnvironment, - commandLinePathFactory, - ImmutableList.of( - defaultHelper.getPathString(), "example.com=" + exampleComHelper.getPathString())); - assertThat( - credentialHelperProvider3 - .findCredentialHelper(URI.create("https://example.com")) - .get() - .getPath()) - .isEqualTo(exampleComHelper); - assertThat( - credentialHelperProvider3 - .findCredentialHelper(URI.create("https://foo.example.com")) - .get() - .getPath()) - .isEqualTo(defaultHelper); - - // Exact match without default. - CredentialHelperProvider credentialHelperProvider4 = - newCredentialHelperProvider( - credentialHelperEnvironment, - commandLinePathFactory, - ImmutableList.of("example.com=" + exampleComHelper.getPathString())); - assertThat( - credentialHelperProvider4 - .findCredentialHelper(URI.create("https://example.com")) - .get() - .getPath()) - .isEqualTo(exampleComHelper); - assertThat( - credentialHelperProvider4.findCredentialHelper(URI.create("https://foo.example.com"))) - .isEmpty(); - - // Multiple scoped helpers with default. - CredentialHelperProvider credentialHelperProvider5 = - newCredentialHelperProvider( - credentialHelperEnvironment, - commandLinePathFactory, - ImmutableList.of( - defaultHelper.getPathString(), - "example.com=" + exampleComHelper.getPathString(), - "*.foo.example.com=" + fooExampleComHelper.getPathString(), - "*.example.com=" + exampleComWildcardHelper.getPathString(), - "example.org=%workspace%/helpers/example-org")); - assertThat( - credentialHelperProvider5 - .findCredentialHelper(URI.create("https://anotherdomain.com")) - .get() - .getPath()) - .isEqualTo(defaultHelper); - assertThat( - credentialHelperProvider5 - .findCredentialHelper(URI.create("https://example.com")) - .get() - .getPath()) - .isEqualTo(exampleComHelper); - assertThat( - credentialHelperProvider5 - .findCredentialHelper(URI.create("https://foo.example.com")) - .get() - .getPath()) - .isEqualTo(fooExampleComHelper); - assertThat( - credentialHelperProvider5 - .findCredentialHelper(URI.create("https://abc.foo.example.com")) - .get() - .getPath()) - .isEqualTo(fooExampleComHelper); - assertThat( - credentialHelperProvider5 - .findCredentialHelper(URI.create("https://bar.example.com")) - .get() - .getPath()) - .isEqualTo(exampleComWildcardHelper); - assertThat( - credentialHelperProvider5 - .findCredentialHelper(URI.create("https://abc.bar.example.com")) - .get() - .getPath()) - .isEqualTo(exampleComWildcardHelper); - assertThat( - credentialHelperProvider5 - .findCredentialHelper(URI.create("https://example.org")) - .get() - .getPath()) - .isEqualTo(exampleOrgHelper); - - // Helpers override. - CredentialHelperProvider credentialHelperProvider6 = - newCredentialHelperProvider( - credentialHelperEnvironment, - commandLinePathFactory, - ImmutableList.of( - // - unusedHelper.getPathString(), - - // - defaultHelper.getPathString(), - "example.com=" + unusedHelper.getPathString(), - "*.example.com=" + unusedHelper.getPathString(), - "example.org=" + unusedHelper.getPathString(), - "*.example.org=" + exampleOrgHelper.getPathString(), - - // - "*.example.com=" + exampleComWildcardHelper.getPathString(), - "example.org=" + exampleOrgHelper.getPathString(), - "*.foo.example.com=" + unusedHelper.getPathString(), - - // - "example.com=" + exampleComHelper.getPathString(), - "*.foo.example.com=" + fooExampleComHelper.getPathString())); - assertThat( - credentialHelperProvider6 - .findCredentialHelper(URI.create("https://anotherdomain.com")) - .get() - .getPath()) - .isEqualTo(defaultHelper); - assertThat( - credentialHelperProvider6 - .findCredentialHelper(URI.create("https://example.com")) - .get() - .getPath()) - .isEqualTo(exampleComHelper); - assertThat( - credentialHelperProvider6 - .findCredentialHelper(URI.create("https://foo.example.com")) - .get() - .getPath()) - .isEqualTo(fooExampleComHelper); - assertThat( - credentialHelperProvider6 - .findCredentialHelper(URI.create("https://bar.example.com")) - .get() - .getPath()) - .isEqualTo(exampleComWildcardHelper); - assertThat( - credentialHelperProvider6 - .findCredentialHelper(URI.create("https://example.org")) - .get() - .getPath()) - .isEqualTo(exampleOrgHelper); - assertThat( - credentialHelperProvider6 - .findCredentialHelper(URI.create("https://foo.example.org")) - .get() - .getPath()) - .isEqualTo(exampleOrgHelper); - } - - private static Path createExecutable(FileSystem fileSystem, String path) throws IOException { - Preconditions.checkNotNull(fileSystem); - Preconditions.checkNotNull(path); - - return createExecutable(fileSystem.getPath(path)); - } - - private static Path createExecutable(Path path) throws IOException { - Preconditions.checkNotNull(path); - - path.getParentDirectory().createDirectoryAndParents(); - try (OutputStream unused = path.getOutputStream()) { - // Nothing to do. - } - path.setExecutable(true); - - return path; - } - - private static CredentialHelperProvider newCredentialHelperProvider( - CredentialHelperEnvironment credentialHelperEnvironment, - CommandLinePathFactory commandLinePathFactory, - ImmutableList inputs) - throws Exception { - Preconditions.checkNotNull(credentialHelperEnvironment); - Preconditions.checkNotNull(commandLinePathFactory); - Preconditions.checkNotNull(inputs); - - return RemoteModule.newCredentialHelperProvider( - credentialHelperEnvironment, - commandLinePathFactory, - ImmutableList.copyOf( - Iterables.transform(inputs, s -> createUnresolvedScopedCredentialHelper(s)))); - } - - private static UnresolvedScopedCredentialHelper createUnresolvedScopedCredentialHelper( - String input) { - Preconditions.checkNotNull(input); - - try { - return AuthAndTLSOptions.UnresolvedScopedCredentialHelperConverter.INSTANCE.convert(input); - } catch (OptionsParsingException e) { - throw new IllegalStateException(e); - } - } }