Repository: bazelbuild/bazel
Issue: --bes_backend doesn't support reading credentials from .netrc
Labels: type: feature request
untriaged
team-Remote-Exec

`--remote_{downloader,cache,executor}` all support reading credentials from `.netrc`: https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/remote/RemoteModule.java;l=1098;drc=1bc1ce3e0d73c35047c29ef85e832db041e0f238

`--bes_backend` doesn't: https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java;l=79;drc=4cd266aa1dfa53d8c8de44f7895edcfd46f74725 calling into https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtils.java;l=194;drc=4cd266aa1dfa53d8c8de44f7895edcfd46f74725

Found while working on #15856

Issue comments:
cc @tjgq 

Pull request review comments:

Patch that resolved the issue:
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 29250880640ff0..e22da5887e456b 100644
--- a/src/main/java/com/google/devtools/build/lib/authandtls/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/authandtls/BUILD
@@ -15,6 +15,8 @@ java_library(
     srcs = glob(["*.java"]),
     deps = [
         "//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",
         "//src/main/java/com/google/devtools/common/options",
         "//third_party:auth",
         "//third_party:auto_value",
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 bf640f1bfc2aef..67e0d9e9195684 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,6 +19,10 @@
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.vfs.FileSystem;
+import com.google.devtools.build.lib.vfs.Path;
 import io.grpc.CallCredentials;
 import io.grpc.ClientInterceptor;
 import io.grpc.ManagedChannel;
@@ -41,6 +45,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.Nullable;
@@ -186,14 +192,17 @@ private static NettyChannelBuilder newNettyChannelBuilder(String targetUrl, Stri
   }
 
   /**
-   * Create a new {@link CallCredentials} object.
+   * Create a new {@link CallCredentials} object from the authentication flags, or null if no flags
+   * are set.
    *
-   * @throws IOException in case the call credentials can't be constructed.
+   * @throws IOException in case the credentials can't be constructed.
    */
-  public static CallCredentials newCallCredentials(AuthAndTLSOptions options) throws IOException {
-    Credentials creds = newCredentials(options);
-    if (creds != null) {
-      return MoreCallCredentials.from(creds);
+  @Nullable
+  public static CallCredentials newGoogleCallCredentials(AuthAndTLSOptions options)
+      throws IOException {
+    Optional<Credentials> creds = newGoogleCredentials(options);
+    if (creds.isPresent()) {
+      return MoreCallCredentials.from(creds.get());
     }
     return null;
   }
@@ -210,18 +219,52 @@ public static CallCredentialsProvider newCallCredentialsProvider(@Nullable Crede
   }
 
   /**
-   * Create a new {@link Credentials} object, or {@code null} if no options are provided.
+   * Create a new {@link Credentials} with following order:
+   *
+   * <ol>
+   *   <li>If authentication enabled by flags, use it to create credentials
+   *   <li>Use .netrc to provide credentials if exists
+   *   <li>Otherwise, return {@code null}
+   * </ol>
    *
    * @throws IOException in case the credentials can't be constructed.
    */
   @Nullable
-  public static Credentials newCredentials(@Nullable AuthAndTLSOptions options) throws IOException {
+  public static Credentials newCredentials(
+      Reporter reporter,
+      Map<String, String> clientEnv,
+      FileSystem fileSystem,
+      AuthAndTLSOptions authAndTlsOptions)
+      throws IOException {
+    Optional<Credentials> credentials = newGoogleCredentials(authAndTlsOptions);
+
+    if (credentials.isEmpty()) {
+      // Fallback to .netrc if it exists.
+      try {
+        credentials = newCredentialsFromNetrc(clientEnv, fileSystem);
+      } catch (IOException e) {
+        // TODO(yannic): Make this fail the build.
+        reporter.handle(Event.warn(e.getMessage()));
+      }
+    }
+
+    return credentials.orElse(null);
+  }
+
+  /**
+   * Create a new {@link Credentials} object from the authentication flags, or null if no flags are
+   * set.
+   *
+   * @throws IOException in case the credentials can't be constructed.
+   */
+  public static Optional<Credentials> newGoogleCredentials(@Nullable AuthAndTLSOptions options)
+      throws IOException {
     if (options == null) {
-      return null;
+      return Optional.empty();
     } else if (options.googleCredentials != null) {
       // Credentials from file
       try (InputStream authFile = new FileInputStream(options.googleCredentials)) {
-        return newCredentials(authFile, options.googleAuthScopes);
+        return Optional.of(newGoogleCredentialsFromFile(authFile, options.googleAuthScopes));
       } catch (FileNotFoundException e) {
         String message =
             String.format(
@@ -230,10 +273,11 @@ public static Credentials newCredentials(@Nullable AuthAndTLSOptions options) th
         throw new IOException(message, e);
       }
     } else if (options.useGoogleDefaultCredentials) {
-      return newCredentials(
-          null /* Google Application Default Credentials */, options.googleAuthScopes);
+      return Optional.of(
+          newGoogleCredentialsFromFile(
+              null /* Google Application Default Credentials */, options.googleAuthScopes));
     }
-    return null;
+    return Optional.empty();
   }
 
   /**
@@ -242,7 +286,7 @@ public static Credentials newCredentials(@Nullable AuthAndTLSOptions options) th
    * @throws IOException in case the credentials can't be constructed.
    */
   @VisibleForTesting
-  public static Credentials newCredentials(
+  public static Credentials newGoogleCredentialsFromFile(
       @Nullable InputStream credentialsFile, List<String> authScopes) throws IOException {
     try {
       GoogleCredentials creds =
@@ -258,4 +302,40 @@ public static Credentials newCredentials(
       throw new IOException(message, e);
     }
   }
+
+  /**
+   * Create a new {@link Credentials} object by parsing the .netrc file with following order to
+   * search it:
+   *
+   * <ol>
+   *   <li>If environment variable $NETRC exists, use it as the path to the .netrc file
+   *   <li>Fallback to $HOME/.netrc
+   * </ol>
+   *
+   * @return the {@link Credentials} object or {@code null} if there is no .netrc file.
+   * @throws IOException in case the credentials can't be constructed.
+   */
+  @VisibleForTesting
+  static Optional<Credentials> newCredentialsFromNetrc(
+      Map<String, String> clientEnv, FileSystem fileSystem) throws IOException {
+    Optional<String> netrcFileString =
+        Optional.ofNullable(clientEnv.get("NETRC"))
+            .or(() -> Optional.ofNullable(clientEnv.get("HOME")).map(home -> home + "/.netrc"));
+    if (netrcFileString.isEmpty()) {
+      return Optional.empty();
+    }
+
+    Path netrcFile = fileSystem.getPath(netrcFileString.get());
+    if (!netrcFile.exists()) {
+      return Optional.empty();
+    }
+
+    try {
+      Netrc netrc = NetrcParser.parseAndClose(netrcFile.getInputStream());
+      return Optional.of(new NetrcCredentials(netrc));
+    } catch (IOException e) {
+      throw new IOException(
+          "Failed to parse " + netrcFile.getPathString() + ": " + e.getMessage(), e);
+    }
+  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BUILD b/src/main/java/com/google/devtools/build/lib/buildeventservice/BUILD
index 31ff6dd5600e85..bfe3f367142f6f 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BUILD
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BUILD
@@ -57,6 +57,7 @@ java_library(
         "//src/main/java/com/google/devtools/build/lib/util/io:out-err",
         "//src/main/java/com/google/devtools/common/options",
         "//src/main/protobuf:failure_details_java_proto",
+        "//third_party:auth",
         "//third_party:auto_value",
         "//third_party:flogger",
         "//third_party:guava",
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java
index e76b0ecf5c83a2..49878218bca925 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BazelBuildEventServiceModule.java
@@ -14,8 +14,10 @@
 
 package com.google.devtools.build.lib.buildeventservice;
 
+import com.google.auth.Credentials;
 import com.google.auto.value.AutoValue;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
@@ -24,9 +26,11 @@
 import com.google.devtools.build.lib.authandtls.GoogleAuthUtils;
 import com.google.devtools.build.lib.buildeventservice.client.BuildEventServiceClient;
 import com.google.devtools.build.lib.buildeventservice.client.BuildEventServiceGrpcClient;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import io.grpc.ClientInterceptor;
 import io.grpc.ManagedChannel;
 import io.grpc.Metadata;
+import io.grpc.auth.MoreCallCredentials;
 import io.grpc.stub.MetadataUtils;
 import java.io.IOException;
 import java.util.Map;
@@ -70,15 +74,28 @@ protected Class<BuildEventServiceOptions> optionsClass() {
 
   @Override
   protected BuildEventServiceClient getBesClient(
-      BuildEventServiceOptions besOptions, AuthAndTLSOptions authAndTLSOptions) throws IOException {
+      CommandEnvironment env,
+      BuildEventServiceOptions besOptions,
+      AuthAndTLSOptions authAndTLSOptions)
+      throws IOException {
     BackendConfig newConfig = BackendConfig.create(besOptions, authAndTLSOptions);
     if (client == null || !Objects.equals(config, newConfig)) {
       clearBesClient();
+      Preconditions.checkState(config == null);
+      Preconditions.checkState(client == null);
+
+      Credentials credentials =
+          GoogleAuthUtils.newCredentials(
+              env.getReporter(),
+              env.getClientEnv(),
+              env.getRuntime().getFileSystem(),
+              newConfig.authAndTLSOptions());
+
       config = newConfig;
       client =
           new BuildEventServiceGrpcClient(
               newGrpcChannel(config),
-              GoogleAuthUtils.newCallCredentials(config.authAndTLSOptions()),
+              credentials != null ? MoreCallCredentials.from(credentials) : null,
               makeGrpcInterceptor(config));
     }
     return client;
diff --git a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
index b352779c72d8d5..e8bc7d3c2cb06a 100644
--- a/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
+++ b/src/main/java/com/google/devtools/build/lib/buildeventservice/BuildEventServiceModule.java
@@ -677,7 +677,7 @@ private BuildEventServiceTransport createBesTransport(
 
     final BuildEventServiceClient besClient;
     try {
-      besClient = getBesClient(besOptions, authTlsOptions);
+      besClient = getBesClient(cmdEnv, besOptions, authTlsOptions);
     } catch (IOException | OptionsParsingException e) {
       reportError(
           reporter,
@@ -822,7 +822,7 @@ private static AbruptExitException createAbruptExitException(
   protected abstract Class<BESOptionsT> optionsClass();
 
   protected abstract BuildEventServiceClient getBesClient(
-      BESOptionsT besOptions, AuthAndTLSOptions authAndTLSOptions)
+      CommandEnvironment env, BESOptionsT besOptions, AuthAndTLSOptions authAndTLSOptions)
       throws IOException, OptionsParsingException;
 
   protected abstract void clearBesClient();
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 0122226f23a59e..60e9b391c4b43f 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
@@ -49,9 +49,6 @@
 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.Netrc;
-import com.google.devtools.build.lib.authandtls.NetrcCredentials;
-import com.google.devtools.build.lib.authandtls.NetrcParser;
 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;
@@ -1052,94 +1049,6 @@ RemoteActionContextProvider getActionContextProvider() {
     return actionContextProvider;
   }
 
-  /**
-   * Create a new {@link Credentials} object by parsing the .netrc file with following order to
-   * search it:
-   *
-   * <ol>
-   *   <li>If environment variable $NETRC exists, use it as the path to the .netrc file
-   *   <li>Fallback to $HOME/.netrc
-   * </ol>
-   *
-   * @return the {@link Credentials} object or {@code null} if there is no .netrc file.
-   * @throws IOException in case the credentials can't be constructed.
-   */
-  @VisibleForTesting
-  static Credentials newCredentialsFromNetrc(Map<String, String> clientEnv, FileSystem fileSystem)
-      throws IOException {
-    String netrcFileString =
-        Optional.ofNullable(clientEnv.get("NETRC"))
-            .orElseGet(
-                () ->
-                    Optional.ofNullable(clientEnv.get("HOME"))
-                        .map(home -> home + "/.netrc")
-                        .orElse(null));
-    if (netrcFileString == null) {
-      return null;
-    }
-
-    Path netrcFile = fileSystem.getPath(netrcFileString);
-    if (netrcFile.exists()) {
-      try {
-        Netrc netrc = NetrcParser.parseAndClose(netrcFile.getInputStream());
-        return new NetrcCredentials(netrc);
-      } catch (IOException e) {
-        throw new IOException(
-            "Failed to parse " + netrcFile.getPathString() + ": " + e.getMessage(), e);
-      }
-    } else {
-      return null;
-    }
-  }
-
-  /**
-   * Create a new {@link Credentials} with following order:
-   *
-   * <ol>
-   *   <li>If authentication enabled by flags, use it to create credentials
-   *   <li>Use .netrc to provide credentials if exists
-   *   <li>Otherwise, return {@code null}
-   * </ol>
-   *
-   * @throws IOException in case the credentials can't be constructed.
-   */
-  @VisibleForTesting
-  static Credentials newCredentials(
-      Map<String, String> clientEnv,
-      FileSystem fileSystem,
-      Reporter reporter,
-      AuthAndTLSOptions authAndTlsOptions,
-      RemoteOptions remoteOptions)
-      throws IOException {
-    Credentials creds = GoogleAuthUtils.newCredentials(authAndTlsOptions);
-
-    // Fallback to .netrc if it exists
-    if (creds == null) {
-      try {
-        creds = newCredentialsFromNetrc(clientEnv, fileSystem);
-      } catch (IOException e) {
-        reporter.handle(Event.warn(e.getMessage()));
-      }
-
-      try {
-        if (creds != null
-            && remoteOptions.remoteCache != null
-            && Ascii.toLowerCase(remoteOptions.remoteCache).startsWith("http://")
-            && !creds.getRequestMetadata(new URI(remoteOptions.remoteCache)).isEmpty()) {
-          reporter.handle(
-              Event.warn(
-                  "Username and password from .netrc is transmitted in plaintext to "
-                      + remoteOptions.remoteCache
-                      + ". Please consider using an HTTPS endpoint."));
-        }
-      } catch (URISyntaxException e) {
-        throw new IOException(e.getMessage(), e);
-      }
-    }
-
-    return creds;
-  }
-
   @VisibleForTesting
   static CredentialHelperProvider newCredentialHelperProvider(
       CredentialHelperEnvironment environment,
@@ -1163,6 +1072,35 @@ static CredentialHelperProvider newCredentialHelperProvider(
     return builder.build();
   }
 
+  static Credentials newCredentials(
+      Map<String, String> clientEnv,
+      FileSystem fileSystem,
+      Reporter reporter,
+      AuthAndTLSOptions authAndTlsOptions,
+      RemoteOptions remoteOptions)
+      throws IOException {
+    Credentials credentials =
+        GoogleAuthUtils.newCredentials(reporter, clientEnv, fileSystem, authAndTlsOptions);
+
+    try {
+      if (credentials != null
+          && remoteOptions.remoteCache != null
+          && Ascii.toLowerCase(remoteOptions.remoteCache).startsWith("http://")
+          && !credentials.getRequestMetadata(new URI(remoteOptions.remoteCache)).isEmpty()) {
+        // TODO(yannic): Make this a error aborting the build.
+        reporter.handle(
+            Event.warn(
+                "Credentials are transmitted in plaintext to "
+                    + remoteOptions.remoteCache
+                    + ". Please consider using an HTTPS endpoint."));
+      }
+    } catch (URISyntaxException e) {
+      throw new IOException(e.getMessage(), e);
+    }
+
+    return credentials;
+  }
+
   @VisibleForTesting
   @AutoValue
   abstract static class ScopedCredentialHelper {


Test patch:
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 b2fbbd60ec8b8e..1e498ca33c4db3 100644
--- a/src/test/java/com/google/devtools/build/lib/authandtls/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/authandtls/BUILD
@@ -25,7 +25,11 @@ java_library(
     ),
     deps = [
         "//src/main/java/com/google/devtools/build/lib/authandtls",
+        "//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",
+        "//src/test/java/com/google/devtools/build/lib/testutil",
+        "//third_party:auth",
         "//third_party:guava",
         "//third_party:junit4",
         "//third_party:mockito",
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
new file mode 100644
index 00000000000000..a3dc50273d82ae
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/authandtls/GoogleAuthUtilsTest.java
@@ -0,0 +1,111 @@
+// Copyright 2022 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.authandtls;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth8.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.auth.Credentials;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+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.inmemoryfs.InMemoryFileSystem;
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class GoogleAuthUtilsTest {
+  @Test
+  public void testNetrc_emptyEnv_shouldIgnore() throws Exception {
+    ImmutableMap<String, String> clientEnv = ImmutableMap.of();
+    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
+
+    assertThat(GoogleAuthUtils.newCredentialsFromNetrc(clientEnv, fileSystem)).isEmpty();
+  }
+
+  @Test
+  public void testNetrc_netrcNotExist_shouldIgnore() throws Exception {
+    String home = "/home/foo";
+    ImmutableMap<String, String> clientEnv = ImmutableMap.of("HOME", home);
+    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
+
+    assertThat(GoogleAuthUtils.newCredentialsFromNetrc(clientEnv, fileSystem)).isEmpty();
+  }
+
+  @Test
+  public void testNetrc_netrcExist_shouldUse() throws Exception {
+    String home = "/home/foo";
+    ImmutableMap<String, String> clientEnv = ImmutableMap.of("HOME", home);
+    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
+    Scratch scratch = new Scratch(fileSystem);
+    scratch.file(home + "/.netrc", "machine foo.example.org login foouser password foopass");
+
+    Optional<Credentials> credentials =
+        GoogleAuthUtils.newCredentialsFromNetrc(clientEnv, fileSystem);
+
+    assertThat(credentials).isPresent();
+    assertRequestMetadata(
+        credentials.get().getRequestMetadata(URI.create("https://foo.example.org")),
+        "foouser",
+        "foopass");
+  }
+
+  @Test
+  public void testNetrc_netrcFromNetrcEnvExist_shouldUse() throws Exception {
+    String home = "/home/foo";
+    String netrc = "/.netrc";
+    ImmutableMap<String, String> clientEnv = ImmutableMap.of("HOME", home, "NETRC", netrc);
+    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
+    Scratch scratch = new Scratch(fileSystem);
+    scratch.file(home + "/.netrc", "machine foo.example.org login foouser password foopass");
+    scratch.file(netrc, "machine foo.example.org login baruser password barpass");
+
+    Optional<Credentials> credentials =
+        GoogleAuthUtils.newCredentialsFromNetrc(clientEnv, fileSystem);
+
+    assertThat(credentials).isPresent();
+    assertRequestMetadata(
+        credentials.get().getRequestMetadata(URI.create("https://foo.example.org")),
+        "baruser",
+        "barpass");
+  }
+
+  @Test
+  public void testNetrc_netrcFromNetrcEnvNotExist_shouldIgnore() throws Exception {
+    String home = "/home/foo";
+    String netrc = "/.netrc";
+    ImmutableMap<String, String> clientEnv = ImmutableMap.of("HOME", home, "NETRC", netrc);
+    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
+    Scratch scratch = new Scratch(fileSystem);
+    scratch.file(home + "/.netrc", "machine foo.example.org login foouser password foopass");
+
+    assertThat(GoogleAuthUtils.newCredentialsFromNetrc(clientEnv, fileSystem)).isEmpty();
+  }
+
+  private static void assertRequestMetadata(
+      Map<String, List<String>> requestMetadata, String username, String password) {
+    assertThat(requestMetadata.keySet()).containsExactly("Authorization");
+    assertThat(Iterables.getOnlyElement(requestMetadata.values()))
+        .containsExactly(BasicHttpAuthenticationEncoder.encode(username, password, UTF_8));
+  }
+}
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 88d69b7436bf37..e0e9aadb50a40f 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/remote/BUILD
@@ -44,17 +44,14 @@ java_test(
         "//src/main/java/com/google/devtools/build/lib:runtime",
         "//src/main/java/com/google/devtools/build/lib/actions",
         "//src/main/java/com/google/devtools/build/lib/actions:action_input_helper",
-        "//src/main/java/com/google/devtools/build/lib/actions:action_lookup_data",
         "//src/main/java/com/google/devtools/build/lib/actions:artifacts",
         "//src/main/java/com/google/devtools/build/lib/actions:execution_requirements",
         "//src/main/java/com/google/devtools/build/lib/actions:file_metadata",
         "//src/main/java/com/google/devtools/build/lib/actions:localhost_capacity",
         "//src/main/java/com/google/devtools/build/lib/analysis:blaze_directories",
         "//src/main/java/com/google/devtools/build/lib/analysis:blaze_version_info",
-        "//src/main/java/com/google/devtools/build/lib/analysis:config/build_options",
         "//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/analysis/platform:platform_utils",
         "//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",
@@ -79,7 +76,6 @@ java_test(
         "//src/main/java/com/google/devtools/build/lib/remote/util",
         "//src/main/java/com/google/devtools/build/lib/runtime/commands",
         "//src/main/java/com/google/devtools/build/lib/skyframe:tree_artifact_value",
-        "//src/main/java/com/google/devtools/build/lib/util",
         "//src/main/java/com/google/devtools/build/lib/util:abrupt_exit_exception",
         "//src/main/java/com/google/devtools/build/lib/util:exit_code",
         "//src/main/java/com/google/devtools/build/lib/util/io",
@@ -95,7 +91,6 @@ java_test(
         "//src/test/java/com/google/devtools/build/lib/exec/util",
         "//src/test/java/com/google/devtools/build/lib/remote/util",
         "//src/test/java/com/google/devtools/build/lib/testutil",
-        "//src/test/java/com/google/devtools/build/lib/testutil:JunitUtils",
         "//src/test/java/com/google/devtools/build/lib/testutil:TestUtils",
         "//third_party:api_client",
         "//third_party:auth",
diff --git a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java b/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java
index 28d4997c39f523..2048f0c0214fe8 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/GrpcCacheClientTest.java
@@ -219,7 +219,7 @@ protected GrpcCacheClient newClient(
     try (InputStream in = scratch.resolve(authTlsOptions.googleCredentials).getInputStream()) {
       callCredentialsProvider =
           GoogleAuthUtils.newCallCredentialsProvider(
-              GoogleAuthUtils.newCredentials(in, authTlsOptions.googleAuthScopes));
+              GoogleAuthUtils.newGoogleCredentialsFromFile(in, authTlsOptions.googleAuthScopes));
     }
     CallCredentials creds = callCredentialsProvider.getCallCredentials();
 
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 e15cdf3ecbe2c4..94479e9ad7544c 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
@@ -15,7 +15,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.common.truth.Truth8.assertThat;
-import static java.nio.charset.StandardCharsets.UTF_8;
 import static org.junit.Assert.assertThrows;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -38,7 +37,6 @@
 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.BasicHttpAuthenticationEncoder;
 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;
@@ -77,7 +75,6 @@
 import java.net.URI;
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -489,77 +486,6 @@ public void getCapabilities(
     }
   }
 
-  @Test
-  public void testNetrc_emptyEnv_shouldIgnore() throws Exception {
-    Map<String, String> clientEnv = ImmutableMap.of();
-    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
-
-    Credentials credentials = RemoteModule.newCredentialsFromNetrc(clientEnv, fileSystem);
-
-    assertThat(credentials).isNull();
-  }
-
-  @Test
-  public void testNetrc_netrcNotExist_shouldIgnore() throws Exception {
-    String home = "/home/foo";
-    Map<String, String> clientEnv = ImmutableMap.of("HOME", home);
-    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
-
-    Credentials credentials = RemoteModule.newCredentialsFromNetrc(clientEnv, fileSystem);
-
-    assertThat(credentials).isNull();
-  }
-
-  @Test
-  public void testNetrc_netrcExist_shouldUse() throws Exception {
-    String home = "/home/foo";
-    Map<String, String> clientEnv = ImmutableMap.of("HOME", home);
-    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
-    Scratch scratch = new Scratch(fileSystem);
-    scratch.file(home + "/.netrc", "machine foo.example.org login foouser password foopass");
-
-    Credentials credentials = RemoteModule.newCredentialsFromNetrc(clientEnv, fileSystem);
-
-    assertThat(credentials).isNotNull();
-    assertRequestMetadata(
-        credentials.getRequestMetadata(URI.create("https://foo.example.org")),
-        "foouser",
-        "foopass");
-  }
-
-  @Test
-  public void testNetrc_netrcFromNetrcEnvExist_shouldUse() throws Exception {
-    String home = "/home/foo";
-    String netrc = "/.netrc";
-    Map<String, String> clientEnv = ImmutableMap.of("HOME", home, "NETRC", netrc);
-    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
-    Scratch scratch = new Scratch(fileSystem);
-    scratch.file(home + "/.netrc", "machine foo.example.org login foouser password foopass");
-    scratch.file(netrc, "machine foo.example.org login baruser password barpass");
-
-    Credentials credentials = RemoteModule.newCredentialsFromNetrc(clientEnv, fileSystem);
-
-    assertThat(credentials).isNotNull();
-    assertRequestMetadata(
-        credentials.getRequestMetadata(URI.create("https://foo.example.org")),
-        "baruser",
-        "barpass");
-  }
-
-  @Test
-  public void testNetrc_netrcFromNetrcEnvNotExist_shouldIgnore() throws Exception {
-    String home = "/home/foo";
-    String netrc = "/.netrc";
-    Map<String, String> clientEnv = ImmutableMap.of("HOME", home, "NETRC", netrc);
-    FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
-    Scratch scratch = new Scratch(fileSystem);
-    scratch.file(home + "/.netrc", "machine foo.example.org login foouser password foopass");
-
-    Credentials credentials = RemoteModule.newCredentialsFromNetrc(clientEnv, fileSystem);
-
-    assertThat(credentials).isNull();
-  }
-
   @Test
   public void testNetrc_netrcWithoutRemoteCache() throws Exception {
     String netrc = "/.netrc";
@@ -580,13 +506,6 @@ public void testNetrc_netrcWithoutRemoteCache() throws Exception {
     assertThat(credentials.getRequestMetadata(URI.create("https://bar.example.org"))).isEmpty();
   }
 
-  private static void assertRequestMetadata(
-      Map<String, List<String>> requestMetadata, String username, String password) {
-    assertThat(requestMetadata.keySet()).containsExactly("Authorization");
-    assertThat(Iterables.getOnlyElement(requestMetadata.values()))
-        .containsExactly(BasicHttpAuthenticationEncoder.encode(username, password, UTF_8));
-  }
-
   @Test
   public void testCredentialHelperProvider() throws Exception {
     FileSystem fileSystem = new InMemoryFileSystem(DigestHashFunction.SHA256);
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteServerCapabilitiesTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteServerCapabilitiesTest.java
index 33e4bcf346dd84..0948fe4a419963 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteServerCapabilitiesTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteServerCapabilitiesTest.java
@@ -224,7 +224,7 @@ public int maxConcurrency() {
               }
             });
     CallCredentials creds =
-        GoogleAuthUtils.newCallCredentials(Options.getDefaults(AuthAndTLSOptions.class));
+        GoogleAuthUtils.newGoogleCallCredentials(Options.getDefaults(AuthAndTLSOptions.class));
     RemoteServerCapabilities client =
         new RemoteServerCapabilities("instance", channel.retain(), creds, 3, retrier);
 
diff --git a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java
index bcb5c9c2d15f30..de8fb3a84544b7 100644
--- a/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java
+++ b/src/test/java/com/google/devtools/build/lib/remote/RemoteSpawnRunnerWithGrpcRemoteExecutorTest.java
@@ -286,7 +286,8 @@ public int maxConcurrency() {
         new GrpcRemoteExecutor(channel.retain(), CallCredentialsProvider.NO_CREDENTIALS, retrier);
     CallCredentialsProvider callCredentialsProvider =
         GoogleAuthUtils.newCallCredentialsProvider(
-            GoogleAuthUtils.newCredentials(Options.getDefaults(AuthAndTLSOptions.class)));
+            GoogleAuthUtils.newGoogleCredentials(Options.getDefaults(AuthAndTLSOptions.class))
+                .orElse(null));
     ByteStreamUploader uploader =
         new ByteStreamUploader(
             remoteOptions.remoteInstanceName,
diff --git a/src/test/shell/bazel/remote/remote_execution_http_test.sh b/src/test/shell/bazel/remote/remote_execution_http_test.sh
index 262170ff9e6c15..0565d4dd8142f9 100755
--- a/src/test/shell/bazel/remote/remote_execution_http_test.sh
+++ b/src/test/shell/bazel/remote/remote_execution_http_test.sh
@@ -545,7 +545,7 @@ EOF
       --remote_cache=http://localhost:${http_port} \
       //a:foo &> $TEST_log \
       || fail "Failed to build //a:foo"
-  expect_not_log "WARNING: Username and password from .netrc is transmitted in plaintext" "Should not print warning"
+  expect_not_log "WARNING: Credentials are transmitted in plaintext" "Should not print warning"
 }
 
 function test_remote_http_cache_with_netrc_warning() {
@@ -565,7 +565,7 @@ EOF
       --remote_cache=http://localhost:${http_port} \
       //a:foo &> $TEST_log \
       || fail "Failed to build //a:foo"
-  expect_log "WARNING: Username and password from .netrc is transmitted in plaintext"
+  expect_log "WARNING: Credentials are transmitted in plaintext"
 }
 
 run_suite "Remote execution and remote cache tests"