repository context: on download, also consider integrity checksums sufficient

The function download{,_and_extract} of a repository context allow to provide
checksums that the downloaded file has to have in order for the downlaod considered
to be successful. Traditionally, this was done by providing a parameter 'sha256';
however, it is also possible through the recently provided 'integrity' parameter,
that can take checksums in different form (currently supporting sha256 and sha512).
Consider such a checksum also sufficient for the requirement of not downloading
from plain http URLs without a given checksum introduced in #8607.

Change-Id: I164e1afcdb65124a361321603c7277dc635c05b9
PiperOrigin-RevId: 259323443
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 c9b7d83..bac7c5d 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
@@ -552,7 +552,12 @@
     Map<URI, Map<String, String>> authHeaders = getAuthHeaders(auth);
 
     List<URL> urls =
-        getUrls(url, /* ensureNonEmpty= */ !allowFail, env, !Strings.isNullOrEmpty(sha256));
+        getUrls(
+            url,
+            /* ensureNonEmpty= */ !allowFail,
+            env,
+            /* checksumGiven= */ !Strings.isNullOrEmpty(sha256)
+                || !Strings.isNullOrEmpty(integrity));
     Optional<Checksum> checksum;
     RepositoryFunctionException checksumValidation = null;
     try {
@@ -660,7 +665,12 @@
     Map<URI, Map<String, String>> authHeaders = getAuthHeaders(auth);
 
     List<URL> urls =
-        getUrls(url, /* ensureNonEmpty= */ !allowFail, env, !Strings.isNullOrEmpty(sha256));
+        getUrls(
+            url,
+            /* ensureNonEmpty= */ !allowFail,
+            env,
+            /* checksumGiven= */ !Strings.isNullOrEmpty(sha256)
+                || !Strings.isNullOrEmpty(integrity));
     Optional<Checksum> checksum;
     RepositoryFunctionException checksumValidation = null;
     try {
diff --git a/src/test/shell/bazel/bazel_workspaces_test.sh b/src/test/shell/bazel/bazel_workspaces_test.sh
index ef2b84e..f1229a1 100755
--- a/src/test/shell/bazel/bazel_workspaces_test.sh
+++ b/src/test/shell/bazel/bazel_workspaces_test.sh
@@ -240,6 +240,7 @@
 
   set_workspace_command "repository_ctx.download(\"http://localhost:${fileserver_port}/file.txt\", \"file.txt\", integrity=\"${file_integrity}\")"
 
+  echo 'build --incompatible_disallow_unverified_http_downloads' >> .bazelrc
   build_and_process_log --exclude_rule "//external:local_config_cc"
 
   ensure_contains_exactly 'location: .*repos.bzl:2:3' 1
@@ -263,11 +264,13 @@
   sha512_py='import base64, hashlib, sys; print(base64.b64encode(hashlib.sha512(sys.stdin.read()).digest()))'
   file_integrity="sha512-$(cat "${file}" | python -c "${sha512_py}")"
 
+
   # Start HTTP server with Python
   startup_server "${server_dir}"
 
   set_workspace_command "repository_ctx.download(\"http://localhost:${fileserver_port}/file.txt\", \"file.txt\", integrity=\"${file_integrity}\")"
 
+  echo 'build --incompatible_disallow_unverified_http_downloads' >> .bazelrc
   build_and_process_log --exclude_rule "//external:local_config_cc"
 
   ensure_contains_exactly 'location: .*repos.bzl:2:3' 1
@@ -279,6 +282,37 @@
   ensure_contains_exactly "integrity: \"${file_integrity}\"" 1
 }
 
+function test_download_integrity_malformed() {
+  # Verify that a malformed value for integrity leads to a failing build
+  local server_dir="${TEST_TMPDIR}/server_dir"
+  mkdir -p "${server_dir}"
+  local file="${server_dir}/file.txt"
+  startup_server "${server_dir}"
+  echo 'build --incompatible_disallow_unverified_http_downloads' >> .bazelrc
+  echo "file contents here" > "${file}"
+
+  # Unsupported checksum algorithm
+  file_integrity="This is no a checksum algorithm"
+  set_workspace_command "repository_ctx.download(\"http://localhost:${fileserver_port}/file.txt\", \"file.txt\", integrity=\"${file_integrity}\")"
+  bazel build //:test > "${TEST_log}" 2>&1 && fail "Expected failure" || :
+  expect_log "${file_integrity}"
+  expect_log "[Uu]nsupported checksum algorithm"
+
+  # Syntactically invalid checksum
+  file_integrity="sha512-ThisIsNotASha512Hash"
+  set_workspace_command "repository_ctx.download(\"http://localhost:${fileserver_port}/file.txt\", \"file.txt\", integrity=\"${file_integrity}\")"
+  bazel build //:test > "${TEST_log}" 2>&1 && fail "Expected failure" || :
+  expect_log "${file_integrity}"
+  expect_log "[Ii]nvalid.*checksum"
+
+  # Syntactically correct, but incorrect value
+  file_integrity="sha512-cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
+  set_workspace_command "repository_ctx.download(\"http://localhost:${fileserver_port}/file.txt\", \"file.txt\", integrity=\"${file_integrity}\")"
+  bazel build //:test > "${TEST_log}" 2>&1 && fail "Expected failure" || :
+  expect_log "${file_integrity}"
+  expect_log "[Ii]nvalid.*checksum"
+}
+
 function test_download_then_extract() {
   # Prepare HTTP server with Python
   local server_dir="${TEST_TMPDIR}/server_dir"