Remove support for authentication and .netrc

Fixes #9327

Closes #9343.

PiperOrigin-RevId: 267568221
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
index bac7c5d..63e2875 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/skylark/SkylarkRepositoryContext.java
@@ -80,7 +80,6 @@
 import java.nio.charset.StandardCharsets;
 import java.time.Duration;
 import java.util.ArrayList;
-import java.util.Base64;
 import java.util.List;
 import java.util.Map;
 
@@ -965,7 +964,9 @@
   }
 
   /**
-   * From an authentication dict extract a map of headers.
+   * From an authentication dict extract a map of headers. Due to
+   * https://github.com/bazelbuild/bazel/issues/9327, this fucntion does the validation of the
+   * <code>auth</code> map, but always returns an empty set of headers.
    *
    * <p>Given a dict as provided as "auth" argument, compute a map specifying for each URI provided
    * which additional headers (as usual, represented as a map from Strings to Strings) should
@@ -976,7 +977,6 @@
   private static Map<URI, Map<String, String>> getAuthHeaders(
       SkylarkDict<String, SkylarkDict<Object, Object>> auth)
       throws RepositoryFunctionException, EvalException {
-    ImmutableMap.Builder<URI, Map<String, String>> headers = new ImmutableMap.Builder<>();
     for (Map.Entry<String, SkylarkDict<Object, Object>> entry : auth.entrySet()) {
       try {
         URL url = new URL(entry.getKey());
@@ -990,14 +990,7 @@
                       + entry.getKey()
                       + " without 'login' and 'password' being provided.");
             }
-            String credentials = authMap.get("login") + ":" + authMap.get("password");
-            headers.put(
-                url.toURI(),
-                ImmutableMap.<String, String>of(
-                    "Authorization",
-                    "Basic "
-                        + Base64.getEncoder()
-                            .encodeToString(credentials.getBytes(StandardCharsets.UTF_8))));
+            url.toURI(); // for URL validation.
           }
         }
       } catch (MalformedURLException e) {
@@ -1006,6 +999,7 @@
         throw new EvalException(null, e.getMessage());
       }
     }
-    return headers.build();
+    // TODO(https://github.com/bazelbuild/bazel/issues/9327)
+    return ImmutableMap.of();
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/SkylarkRepositoryContextApi.java b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/SkylarkRepositoryContextApi.java
index 2fe7a7a..7faa55e 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/SkylarkRepositoryContextApi.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkbuildapi/repository/SkylarkRepositoryContextApi.java
@@ -405,7 +405,7 @@
             type = SkylarkDict.class,
             defaultValue = "{}",
             named = true,
-            doc = "An optional dict specifying authentication information for some of the URLs."),
+            doc = "Has no effect; do not use."),
         @Param(
             name = "integrity",
             type = String.class,
@@ -560,7 +560,7 @@
             type = SkylarkDict.class,
             defaultValue = "{}",
             named = true,
-            doc = "An optional dict specifying authentication information for some of the URLs."),
+            doc = "Has no effect; do not use."),
         @Param(
             name = "integrity",
             type = String.class,
diff --git a/src/test/shell/bazel/skylark_repository_test.sh b/src/test/shell/bazel/skylark_repository_test.sh
index 258b23c..33ea537 100755
--- a/src/test/shell/bazel/skylark_repository_test.sh
+++ b/src/test/shell/bazel/skylark_repository_test.sh
@@ -1500,226 +1500,6 @@
   expect_log "//:b.bzl"
 }
 
-function test_auth_provided() {
-  mkdir x
-  echo 'exports_files(["file.txt"])' > x/BUILD
-  echo 'Hello World' > x/file.txt
-  tar cvf x.tar x
-  sha256="$(sha256sum x.tar | head -c 64)"
-  serve_file_auth x.tar
-  cat >> $(create_workspace_with_default_repos WORKSPACE) <<EOF
-load("//:auth.bzl", "with_auth")
-with_auth(
-  name="ext",
-  url = "http://127.0.0.1:$nc_port/x.tar",
-  sha256 = "$sha256",
-)
-EOF
-  cat > auth.bzl <<'EOF'
-def _impl(ctx):
-  ctx.download_and_extract(
-    url = ctx.attr.url,
-    sha256 = ctx.attr.sha256,
-    # Use the username/password pair hard-coded
-    # in the testing server.
-    auth = {ctx.attr.url : { "type": "basic",
-                            "login" : "foo",
-                            "password" : "bar"}}
-  )
-
-with_auth = repository_rule(
-  implementation = _impl,
-  attrs = { "url" : attr.string(), "sha256" : attr.string() }
-)
-EOF
-  cat > BUILD <<'EOF'
-genrule(
-  name = "it",
-  srcs = ["@ext//x:file.txt"],
-  outs = ["it.txt"],
-  cmd = "cp $< $@",
-)
-EOF
-  bazel build //:it \
-      || fail "Expected success despite needing a file behind basic auth"
-}
-
-function test_netrc_reading() {
-  # Write a badly formated, but correct, .netrc file
-  cat > .netrc <<'EOF'
-machine ftp.example.com
-macdef init
-cd pub
-mget *
-quit
-
-machine example.com login
-myusername password mysecret default
-login anonymous password myusername@example.com
-EOF
-  # We expect that `read_netrc` can parse this file...
-  cat > def.bzl <<'EOF'
-load("@bazel_tools//tools/build_defs/repo:utils.bzl", "read_netrc")
-def _impl(ctx):
-  rc = read_netrc(ctx, ctx.attr.path)
-  ctx.file("data.bzl", "netrc = %s" % (rc,))
-  ctx.file("BUILD", "")
-  ctx.file("WORKSPACE", "")
-
-netrcrepo = repository_rule(
-  implementation = _impl,
-  attrs = {"path": attr.string()},
-)
-EOF
-  cat >> $(create_workspace_with_default_repos WORKSPACE) <<EOF
-load("//:def.bzl", "netrcrepo")
-
-netrcrepo(name = "netrc", path="$(pwd)/.netrc")
-EOF
-  # ...and that from the parse result, we can read off the
-  # credentials for example.com.
-  cat > BUILD <<'EOF'
-load("@netrc//:data.bzl", "netrc")
-
-[genrule(
-  name = name,
-  outs = [ "%s.txt" % (name,)],
-  cmd = "echo %s > $@" % (netrc["example.com"][name],),
-) for name in ["login", "password"]]
-EOF
-  bazel build //:login //:password
-  grep 'myusername' `bazel info bazel-genfiles`/login.txt \
-       || fail "Username not parsed correctly"
-  grep 'mysecret' `bazel info bazel-genfiles`/password.txt \
-       || fail "Password not parsed correctly"
-
-  # Also check the precise value of parsed file
-  cat > expected.bzl <<'EOF'
-expected = {
-  "ftp.example.com" : { "macdef init" : "cd pub\nmget *\nquit\n" },
-  "example.com" : { "login" : "myusername",
-                    "password" : "mysecret",
-                  },
-  "" : { "login": "anonymous",
-          "password" : "myusername@example.com" },
-}
-EOF
-  cat > verify.bzl <<'EOF'
-load("@netrc//:data.bzl", "netrc")
-load("//:expected.bzl", "expected")
-
-def check_equal_expected():
-  print("Parsed value:   %s" % (netrc,))
-  print("Expected value: %s" % (expected,))
-  if netrc == expected:
-    return "OK"
-  else:
-    return "BAD"
-EOF
-  cat > BUILD <<'EOF'
-load ("//:verify.bzl", "check_equal_expected")
-genrule(
-  name = "check_expected",
-  outs = ["check_expected.txt"],
-  cmd = "echo %s > $@" % (check_equal_expected(),)
-)
-EOF
-  bazel build //:check_expected
-  grep 'OK' `bazel info bazel-genfiles`/check_expected.txt \
-       || fail "Parsed dict not equal to expected value"
-}
-
-function test_use_netrc() {
-    # Test the starlark utility function use_netrc.
-  cat > .netrc <<'EOF'
-machine foo.example.org
-login foousername
-password foopass
-
-machine bar.example.org
-login barusername
-password passbar
-EOF
-  # Read a given .netrc file and combine it with a list of URL,
-  # and write the obtained authentication dicionary to disk; this
-  # is not the intended way of using, but makes testing easy.
-  cat > def.bzl <<'EOF'
-load("@bazel_tools//tools/build_defs/repo:utils.bzl", "read_netrc", "use_netrc")
-def _impl(ctx):
-  rc = read_netrc(ctx, ctx.attr.path)
-  auth = use_netrc(rc, ctx.attr.urls)
-  ctx.file("data.bzl", "auth = %s" % (auth,))
-  ctx.file("BUILD", "")
-  ctx.file("WORKSPACE", "")
-
-authrepo = repository_rule(
-  implementation = _impl,
-  attrs = {"path": attr.string(),
-           "urls": attr.string_list()
-  },
-)
-EOF
-  cat >> $(create_workspace_with_default_repos WORKSPACE) <<EOF
-load("//:def.bzl", "authrepo")
-
-authrepo(
-  name = "auth",
-  path="$(pwd)/.netrc",
-  urls = [
-    "http://example.org/public/null.tar",
-    "https://foo.example.org/file1.tar",
-    "https://foo.example.org:8080/file2.tar",
-    "https://bar.example.org/file3.tar",
-    "https://evil.com/bar.example.org/file4.tar",
-  ],
-)
-EOF
-  # Here dicts give us the correct notion of equality, so we can simply
-  # compare against the expected value.
-  cat > expected.bzl <<'EOF'
-expected = {
-    "https://foo.example.org/file1.tar" : {
-      "type" : "basic",
-      "login": "foousername",
-      "password" : "foopass",
-    },
-    "https://foo.example.org:8080/file2.tar" : {
-      "type" : "basic",
-      "login": "foousername",
-      "password" : "foopass",
-    },
-    "https://bar.example.org/file3.tar" : {
-      "type" : "basic",
-      "login": "barusername",
-      "password" : "passbar",
-    },
-}
-EOF
-  cat > verify.bzl <<'EOF'
-load("@auth//:data.bzl", "auth")
-load("//:expected.bzl", "expected")
-
-def check_equal_expected():
-  print("Computed value: %s" % (auth,))
-  print("Expected value: %s" % (expected,))
-  if auth == expected:
-    return "OK"
-  else:
-    return "BAD"
-EOF
-  cat > BUILD <<'EOF'
-load ("//:verify.bzl", "check_equal_expected")
-genrule(
-  name = "check_expected",
-  outs = ["check_expected.txt"],
-  cmd = "echo %s > $@" % (check_equal_expected(),)
-)
-EOF
-  bazel build //:check_expected
-  grep 'OK' `bazel info bazel-genfiles`/check_expected.txt \
-       || fail "Authentication merged incorrectly"
-}
-
 function test_disallow_unverified_http() {
   mkdir x
   echo 'exports_files(["file.txt"])' > x/BUILD
@@ -1768,74 +1548,4 @@
   true
 }
 
-function test_http_archive_netrc() {
-  mkdir x
-  echo 'exports_files(["file.txt"])' > x/BUILD
-  echo 'Hello World' > x/file.txt
-  tar cvf x.tar x
-  sha256=$(sha256sum x.tar | head -c 64)
-  serve_file_auth x.tar
-  cat > WORKSPACE <<EOF
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-http_archive(
-  name="ext",
-  url = "http://127.0.0.1:$nc_port/x.tar",
-  netrc = "$(pwd)/.netrc",
-  sha256="$sha256",
-)
-EOF
-  cat > .netrc <<'EOF'
-machine 127.0.0.1
-login foo
-password bar
-EOF
-  cat > BUILD <<'EOF'
-genrule(
-  name = "it",
-  srcs = ["@ext//x:file.txt"],
-  outs = ["it.txt"],
-  cmd = "cp $< $@",
-)
-EOF
-  bazel build //:it \
-      || fail "Expected success despite needing a file behind basic auth"
-}
-
-function test_implicit_netrc() {
-  mkdir x
-  echo 'exports_files(["file.txt"])' > x/BUILD
-  echo 'Hello World' > x/file.txt
-  tar cvf x.tar x
-  sha256=$(sha256sum x.tar | head -c 64)
-  serve_file_auth x.tar
-
-  export HOME=`pwd`
-  cat > .netrc <<'EOF'
-machine 127.0.0.1
-login foo
-password bar
-EOF
-
-  mkdir main
-  cd main
-  cat > WORKSPACE <<EOF
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-http_archive(
-  name="ext",
-  url = "http://127.0.0.1:$nc_port/x.tar",
-  sha256="$sha256",
-)
-EOF
-  cat > BUILD <<'EOF'
-genrule(
-  name = "it",
-  srcs = ["@ext//x:file.txt"],
-  outs = ["it.txt"],
-  cmd = "cp $< $@",
-)
-EOF
-  bazel build //:it \
-      || fail "Expected success despite needing a file behind basic auth"
-}
-
 run_suite "local repository tests"
diff --git a/tools/build_defs/repo/http.bzl b/tools/build_defs/repo/http.bzl
index da4bf88..180e078 100644
--- a/tools/build_defs/repo/http.bzl
+++ b/tools/build_defs/repo/http.bzl
@@ -26,36 +26,15 @@
 )
 ```
 
-These rules are improved versions of the native http rules and will eventually
-replace the native rules.
 """
 
 load(
     ":utils.bzl",
     "patch",
-    "read_netrc",
     "update_attrs",
-    "use_netrc",
     "workspace_and_buildfile",
 )
 
-def _get_auth(ctx, urls):
-    """Given the list of URLs obtain the correct auth dict."""
-    if ctx.attr.netrc:
-        netrc = read_netrc(ctx, ctx.attr.netrc)
-        return use_netrc(netrc, urls)
-
-    if "HOME" in ctx.os.environ:
-        if not ctx.os.name.startswith("windows"):
-            netrcfile = "%s/.netrc" % (ctx.os.environ["HOME"],)
-            if ctx.execute(["test", "-f", netrcfile]).return_code == 0:
-                netrc = read_netrc(ctx, netrcfile)
-                return use_netrc(netrc, urls)
-
-        # TODO: Search at a similarly canonical place for Windows as well
-
-    return {}
-
 def _http_archive_impl(ctx):
     """Implementation of the http_archive rule."""
     if not ctx.attr.url and not ctx.attr.urls:
@@ -69,8 +48,6 @@
     if ctx.attr.url:
         all_urls = [ctx.attr.url] + all_urls
 
-    auth = _get_auth(ctx, all_urls)
-
     download_info = ctx.download_and_extract(
         all_urls,
         "",
@@ -78,7 +55,6 @@
         ctx.attr.type,
         ctx.attr.strip_prefix,
         canonical_id = ctx.attr.canonical_id,
-        auth = auth,
     )
     patch(ctx)
     workspace_and_buildfile(ctx)
@@ -109,13 +85,11 @@
     download_path = ctx.path("file/" + downloaded_file_path)
     if download_path in forbidden_files or not str(download_path).startswith(str(repo_root)):
         fail("'%s' cannot be used as downloaded_file_path in http_file" % ctx.attr.downloaded_file_path)
-    auth = _get_auth(ctx, ctx.attr.urls)
     download_info = ctx.download(
         ctx.attr.urls,
         "file/" + downloaded_file_path,
         ctx.attr.sha256,
         ctx.attr.executable,
-        auth = auth,
     )
     ctx.file("WORKSPACE", "workspace(name = \"{name}\")".format(name = ctx.name))
     ctx.file("file/BUILD", _HTTP_FILE_BUILD.format(downloaded_file_path))
@@ -146,12 +120,10 @@
         all_urls = ctx.attr.urls
     if ctx.attr.url:
         all_urls = [ctx.attr.url] + all_urls
-    auth = _get_auth(ctx, all_urls)
     download_info = ctx.download(
         all_urls,
         "jar/downloaded.jar",
         ctx.attr.sha256,
-        auth = auth,
     )
     ctx.file("WORKSPACE", "workspace(name = \"{name}\")".format(name = ctx.name))
     ctx.file("jar/BUILD", _HTTP_JAR_BUILD)
@@ -185,9 +157,7 @@
 field will make your build non-hermetic. It is optional to make development
 easier but should be set before shipping.""",
     ),
-    "netrc": attr.string(
-        doc = "Location of the .netrc file to use for authentication",
-    ),
+    "netrc": attr.string(),
     "canonical_id": attr.string(
         doc = """A canonical id of the archive downloaded
 
@@ -364,9 +334,7 @@
 Each entry must be a file, http or https URL. Redirections are followed.
 Authentication is not supported.""",
     ),
-    "netrc": attr.string(
-        doc = "Location of the .netrc file to use for authentication",
-    ),
+    "netrc": attr.string(),
 }
 
 http_file = repository_rule(
@@ -408,9 +376,7 @@
             "A list of URLS the jar can be fetched from. They have to end " +
             "in `.jar`.",
     ),
-    "netrc": attr.string(
-        doc = "Location of the .netrc file to use for authentication",
-    ),
+    "netrc": attr.string(),
 }
 
 http_jar = repository_rule(
diff --git a/tools/build_defs/repo/utils.bzl b/tools/build_defs/repo/utils.bzl
index 5e7b4aa..ed4363b 100644
--- a/tools/build_defs/repo/utils.bzl
+++ b/tools/build_defs/repo/utils.bzl
@@ -167,124 +167,3 @@
     """
     if name not in native.existing_rules():
         repo_rule(name = name, **kwargs)
-
-def read_netrc(ctx, filename):
-    """Utility function to parse at least a basic .netrc file.
-
-    Args:
-      ctx: The repository context of the repository rule calling this utility
-        function.
-      filename: the name of the .netrc file to read
-
-    Returns:
-      dict mapping a machine names to a dict with the information provided
-      about them
-    """
-    contents = ctx.read(filename)
-
-    # Parse the file. This is mainly a token-based update of a simple state
-    # machine, but we need to keep the line structure to correctly determine
-    # the end of a `macdef` command.
-    netrc = {}
-    currentmachinename = None
-    currentmachine = {}
-    macdef = None
-    currentmacro = ""
-    cmd = None
-    for line in contents.splitlines():
-        if macdef:
-            # as we're in a macro, just determine if we reached the end.
-            if line:
-                currentmacro += line + "\n"
-            else:
-                # reached end of macro, add it
-                currentmachine[macdef] = currentmacro
-                macdef = None
-                currentmacro = ""
-        else:
-            # Essentially line.split(None) which starlark does not support.
-            tokens = [
-                w.strip()
-                for w in line.split(" ")
-                if len(w.strip()) > 0
-            ]
-            for token in tokens:
-                if cmd:
-                    # we have a command that expects another argument
-                    if cmd == "machine":
-                        # a new machine definition was provided, so save the
-                        # old one, if present
-                        if not currentmachinename == None:
-                            netrc[currentmachinename] = currentmachine
-                        currentmachine = {}
-                        currentmachinename = token
-                    elif cmd == "macdef":
-                        macdef = "macdef %s" % (token,)
-                        # a new macro definition; the documentation says
-                        # "its contents begin with the next .netrc line [...]",
-                        # so should there really be tokens left in the current
-                        # line, they're not part of the macro.
-
-                    else:
-                        currentmachine[cmd] = token
-                    cmd = None
-                elif token in [
-                    "machine",
-                    "login",
-                    "password",
-                    "account",
-                    "macdef",
-                ]:
-                    # command takes one argument
-                    cmd = token
-                elif token == "default":
-                    # defines the default machine; again, store old machine
-                    if not currentmachinename == None:
-                        netrc[currentmachinename] = currentmachine
-
-                    # We use the empty string for the default machine, as that
-                    # can never be a valid hostname ("default" could be, in the
-                    # default search domain).
-                    currentmachinename = ""
-                    currentmachine = {}
-                else:
-                    fail("Unexpected token '%s' while reading %s" %
-                         (token, filename))
-    if not currentmachinename == None:
-        netrc[currentmachinename] = currentmachine
-    return netrc
-
-def use_netrc(netrc, urls):
-    """compute an auth dict from a parsed netrc file and a list of URLs
-
-    Args:
-      netrc: a netrc file already parsed to a dict, e.g., as obtained from
-        read_netrc
-      urls: a list of URLs.
-
-    Returns:
-      dict suitable as auth argument for ctx.download; more precisely, the dict
-      will map all URLs where the netrc file provides login and password to a
-      dict containing the corresponding login and passwored, as well as the
-      mapping of "type" to "basic"
-    """
-    auth = {}
-    for url in urls:
-        schemerest = url.split("://", 1)
-        if len(schemerest) < 2:
-            continue
-        if not (schemerest[0] in ["http", "https"]):
-            # For other protocols, bazel currently does not support
-            # authentication. So ignore them.
-            continue
-        host = schemerest[1].split("/")[0].split(":")[0]
-        if not host in netrc:
-            continue
-        authforhost = netrc[host]
-        if "login" in authforhost and "password" in authforhost:
-            auth[url] = {
-                "type": "basic",
-                "login": authforhost["login"],
-                "password": authforhost["password"],
-            }
-    return auth