Skip to content

Commit 38c5019

Browse files
authored
[remote/downloader] Migrate Downloader to take Credentials (bazelbuild#16732)
Progress on bazelbuild#15856 Closes bazelbuild#16601. PiperOrigin-RevId: 485837451 Change-Id: I785882d0ff3e171dcaee6aa6f628bca9232c730a
1 parent f589512 commit 38c5019

File tree

12 files changed

+111
-46
lines changed

12 files changed

+111
-46
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2022 The Bazel Authors. All rights reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.devtools.build.lib.authandtls;
16+
17+
import com.google.auth.Credentials;
18+
import com.google.common.base.Preconditions;
19+
import com.google.common.collect.ImmutableMap;
20+
import java.net.URI;
21+
import java.util.List;
22+
import java.util.Map;
23+
24+
/** Implementation of {@link Credentials} which provides a static set of credentials. */
25+
public final class StaticCredentials extends Credentials {
26+
public static final StaticCredentials EMPTY = new StaticCredentials(ImmutableMap.of());
27+
28+
private final ImmutableMap<URI, Map<String, List<String>>> credentials;
29+
30+
public StaticCredentials(Map<URI, Map<String, List<String>>> credentials) {
31+
Preconditions.checkNotNull(credentials);
32+
33+
this.credentials = ImmutableMap.copyOf(credentials);
34+
}
35+
36+
@Override
37+
public String getAuthenticationType() {
38+
return "static";
39+
}
40+
41+
@Override
42+
public Map<String, List<String>> getRequestMetadata(URI uri) {
43+
Preconditions.checkNotNull(uri);
44+
45+
return credentials.getOrDefault(uri, ImmutableMap.of());
46+
}
47+
48+
@Override
49+
public boolean hasRequestMetadata() {
50+
return true;
51+
}
52+
53+
@Override
54+
public boolean hasRequestMetadataOnly() {
55+
return true;
56+
}
57+
58+
@Override
59+
public void refresh() {
60+
// Can't refresh static credentials.
61+
}
62+
}

src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DelegatingDownloader.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
package com.google.devtools.build.lib.bazel.repository.downloader;
1616

17+
import com.google.auth.Credentials;
1718
import com.google.common.base.Optional;
1819
import com.google.devtools.build.lib.events.ExtendedEventHandler;
1920
import com.google.devtools.build.lib.vfs.Path;
2021
import java.io.IOException;
21-
import java.net.URI;
2222
import java.net.URL;
2323
import java.util.List;
2424
import java.util.Map;
@@ -47,7 +47,7 @@ public void setDelegate(@Nullable Downloader delegate) {
4747
@Override
4848
public void download(
4949
List<URL> urls,
50-
Map<URI, Map<String, List<String>>> authHeaders,
50+
Credentials credentials,
5151
Optional<Checksum> checksum,
5252
String canonicalId,
5353
Path destination,
@@ -60,6 +60,6 @@ public void download(
6060
downloader = delegate;
6161
}
6262
downloader.download(
63-
urls, authHeaders, checksum, canonicalId, destination, eventHandler, clientEnv, type);
63+
urls, credentials, checksum, canonicalId, destination, eventHandler, clientEnv, type);
6464
}
6565
}

src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/DownloadManager.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.common.collect.ImmutableList;
2525
import com.google.common.collect.ImmutableMap;
2626
import com.google.common.collect.ImmutableSet;
27+
import com.google.devtools.build.lib.authandtls.StaticCredentials;
2728
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache;
2829
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache.KeyType;
2930
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCacheHitEvent;
@@ -256,7 +257,7 @@ public Path download(
256257
try {
257258
downloader.download(
258259
rewrittenUrls,
259-
rewrittenAuthHeaders,
260+
new StaticCredentials(rewrittenAuthHeaders),
260261
checksum,
261262
canonicalId,
262263
destination,
@@ -337,7 +338,7 @@ public byte[] downloadAndReadOneUrl(
337338
for (int attempt = 0; attempt <= retries; ++attempt) {
338339
try {
339340
return httpDownloader.downloadAndReadOneUrl(
340-
rewrittenUrls.get(0), authHeaders, eventHandler, clientEnv);
341+
rewrittenUrls.get(0), new StaticCredentials(authHeaders), eventHandler, clientEnv);
341342
} catch (ContentLengthMismatchException e) {
342343
if (attempt == retries) {
343344
throw e;

src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/Downloader.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414

1515
package com.google.devtools.build.lib.bazel.repository.downloader;
1616

17+
import com.google.auth.Credentials;
1718
import com.google.common.base.Optional;
1819
import com.google.devtools.build.lib.events.ExtendedEventHandler;
1920
import com.google.devtools.build.lib.vfs.Path;
2021
import java.io.IOException;
21-
import java.net.URI;
2222
import java.net.URL;
2323
import java.util.List;
2424
import java.util.Map;
@@ -33,7 +33,7 @@ public interface Downloader {
3333
* caller is responsible for cleaning up outputs of failed downloads.
3434
*
3535
* @param urls list of mirror URLs with identical content
36-
* @param authHeaders map of authentication headers per URL
36+
* @param credentials credentials to use when connecting to URLs
3737
* @param checksum valid checksum which is checked, or absent to disable
3838
* @param output path to the destination file to write
3939
* @param type extension, e.g. "tar.gz" to force on downloaded filename, or empty to not do this
@@ -42,7 +42,7 @@ public interface Downloader {
4242
*/
4343
void download(
4444
List<URL> urls,
45-
Map<URI, Map<String, List<String>>> authHeaders,
45+
Credentials credentials,
4646
Optional<Checksum> checksum,
4747
String canonicalId,
4848
Path output,

src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexer.java

+17-20
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,21 @@
1414

1515
package com.google.devtools.build.lib.bazel.repository.downloader;
1616

17+
import com.google.auth.Credentials;
1718
import com.google.common.annotations.VisibleForTesting;
1819
import com.google.common.base.Function;
1920
import com.google.common.base.Optional;
2021
import com.google.common.base.Preconditions;
2122
import com.google.common.collect.ImmutableList;
2223
import com.google.common.collect.ImmutableMap;
2324
import com.google.devtools.build.lib.analysis.BlazeVersionInfo;
25+
import com.google.devtools.build.lib.authandtls.StaticCredentials;
2426
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
2527
import com.google.devtools.build.lib.events.Event;
2628
import com.google.devtools.build.lib.events.EventHandler;
2729
import java.io.IOException;
2830
import java.io.InputStream;
2931
import java.io.InterruptedIOException;
30-
import java.net.URI;
3132
import java.net.URISyntaxException;
3233
import java.net.URL;
3334
import java.net.URLConnection;
@@ -74,7 +75,7 @@ final class HttpConnectorMultiplexer {
7475
}
7576

7677
public HttpStream connect(URL url, Optional<Checksum> checksum) throws IOException {
77-
return connect(url, checksum, ImmutableMap.of(), Optional.absent());
78+
return connect(url, checksum, StaticCredentials.EMPTY, Optional.absent());
7879
}
7980

8081
/**
@@ -87,25 +88,22 @@ public HttpStream connect(URL url, Optional<Checksum> checksum) throws IOExcepti
8788
*
8889
* @param url the URL to conenct to. can be: file, http, or https
8990
* @param checksum checksum lazily checked on entire payload, or empty to disable
90-
* @param authHeaders the authentication headers
91+
* @param credentials the credentials
9192
* @param type extension, e.g. "tar.gz" to force on downloaded filename, or empty to not do this
9293
* @return an {@link InputStream} of response payload
9394
* @throws IOException if all mirrors are down and contains suppressed exception of each attempt
9495
* @throws InterruptedIOException if current thread is being cast into oblivion
9596
* @throws IllegalArgumentException if {@code urls} is empty or has an unsupported protocol
9697
*/
9798
public HttpStream connect(
98-
URL url,
99-
Optional<Checksum> checksum,
100-
Map<URI, Map<String, List<String>>> authHeaders,
101-
Optional<String> type)
99+
URL url, Optional<Checksum> checksum, Credentials credentials, Optional<String> type)
102100
throws IOException {
103101
Preconditions.checkArgument(HttpUtils.isUrlSupportedByDownloader(url));
104102
if (Thread.interrupted()) {
105103
throw new InterruptedIOException();
106104
}
107105
Function<URL, ImmutableMap<String, List<String>>> headerFunction =
108-
getHeaderFunction(REQUEST_HEADERS, authHeaders);
106+
getHeaderFunction(REQUEST_HEADERS, credentials);
109107
URLConnection connection = connector.connect(url, headerFunction);
110108
return httpStreamFactory.create(
111109
connection,
@@ -127,21 +125,20 @@ public HttpStream connect(
127125

128126
@VisibleForTesting
129127
static Function<URL, ImmutableMap<String, List<String>>> getHeaderFunction(
130-
Map<String, List<String>> baseHeaders,
131-
Map<URI, Map<String, List<String>>> additionalHeaders) {
128+
Map<String, List<String>> baseHeaders, Credentials credentials) {
129+
Preconditions.checkNotNull(baseHeaders);
130+
Preconditions.checkNotNull(credentials);
131+
132132
return url -> {
133-
ImmutableMap<String, List<String>> headers = ImmutableMap.copyOf(baseHeaders);
133+
Map<String, List<String>> headers = new HashMap<>(baseHeaders);
134134
try {
135-
if (additionalHeaders.containsKey(url.toURI())) {
136-
Map<String, List<String>> newHeaders = new HashMap<>(headers);
137-
newHeaders.putAll(additionalHeaders.get(url.toURI()));
138-
headers = ImmutableMap.copyOf(newHeaders);
139-
}
140-
} catch (URISyntaxException e) {
141-
// If we can't convert the URL to a URI (because it is syntactically malformed), still try
142-
// to do the connection, not adding authentication information as we cannot look it up.
135+
headers.putAll(credentials.getRequestMetadata(url.toURI()));
136+
} catch (URISyntaxException | IOException e) {
137+
// If we can't convert the URL to a URI (because it is syntactically malformed), or fetching
138+
// credentials fails for any other reason, still try to do the connection, not adding
139+
// authentication information as we cannot look it up.
143140
}
144-
return headers;
141+
return ImmutableMap.copyOf(headers);
145142
};
146143
}
147144
}

src/main/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpDownloader.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.devtools.build.lib.bazel.repository.downloader;
1616

17+
import com.google.auth.Credentials;
1718
import com.google.common.base.Optional;
1819
import com.google.common.collect.ImmutableList;
1920
import com.google.common.collect.Iterables;
@@ -31,7 +32,6 @@
3132
import java.io.InterruptedIOException;
3233
import java.io.OutputStream;
3334
import java.net.SocketTimeoutException;
34-
import java.net.URI;
3535
import java.net.URL;
3636
import java.util.ArrayList;
3737
import java.util.List;
@@ -63,7 +63,7 @@ public void setTimeoutScaling(float timeoutScaling) {
6363
@Override
6464
public void download(
6565
List<URL> urls,
66-
Map<URI, Map<String, List<String>>> authHeaders,
66+
Credentials credentials,
6767
Optional<Checksum> checksum,
6868
String canonicalId,
6969
Path destination,
@@ -82,7 +82,7 @@ public void download(
8282
for (URL url : urls) {
8383
SEMAPHORE.acquire();
8484

85-
try (HttpStream payload = multiplexer.connect(url, checksum, authHeaders, type);
85+
try (HttpStream payload = multiplexer.connect(url, checksum, credentials, type);
8686
OutputStream out = destination.getOutputStream()) {
8787
try {
8888
ByteStreams.copy(payload, out);
@@ -132,7 +132,7 @@ public void download(
132132
/** Downloads the contents of one URL and reads it into a byte array. */
133133
public byte[] downloadAndReadOneUrl(
134134
URL url,
135-
Map<URI, Map<String, List<String>>> authHeaders,
135+
Credentials credentials,
136136
ExtendedEventHandler eventHandler,
137137
Map<String, String> clientEnv)
138138
throws IOException, InterruptedException {
@@ -141,7 +141,7 @@ public byte[] downloadAndReadOneUrl(
141141
ByteArrayOutputStream out = new ByteArrayOutputStream();
142142
SEMAPHORE.acquire();
143143
try (HttpStream payload =
144-
multiplexer.connect(url, Optional.absent(), authHeaders, Optional.absent())) {
144+
multiplexer.connect(url, Optional.absent(), credentials, Optional.absent())) {
145145
ByteStreams.copy(payload, out);
146146
} catch (SocketTimeoutException e) {
147147
// SocketTimeoutExceptions are InterruptedIOExceptions; however they do not signify

src/main/java/com/google/devtools/build/lib/remote/downloader/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ java_library(
2222
"//src/main/java/com/google/devtools/build/lib/remote/options",
2323
"//src/main/java/com/google/devtools/build/lib/remote/util",
2424
"//src/main/java/com/google/devtools/build/lib/vfs",
25+
"//third_party:auth",
2526
"//third_party:guava",
2627
"//third_party:jsr305",
2728
"//third_party/grpc-java:grpc-jar",

src/main/java/com/google/devtools/build/lib/remote/downloader/GrpcRemoteDownloader.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import build.bazel.remote.asset.v1.Qualifier;
2222
import build.bazel.remote.execution.v2.Digest;
2323
import build.bazel.remote.execution.v2.RequestMetadata;
24+
import com.google.auth.Credentials;
2425
import com.google.common.annotations.VisibleForTesting;
2526
import com.google.common.base.Strings;
2627
import com.google.devtools.build.lib.bazel.repository.downloader.Checksum;
@@ -41,7 +42,6 @@
4142
import io.grpc.StatusRuntimeException;
4243
import java.io.IOException;
4344
import java.io.OutputStream;
44-
import java.net.URI;
4545
import java.net.URL;
4646
import java.util.List;
4747
import java.util.Map;
@@ -110,7 +110,7 @@ public void close() {
110110
@Override
111111
public void download(
112112
List<URL> urls,
113-
Map<URI, Map<String, List<String>>> authHeaders,
113+
Credentials credentials,
114114
com.google.common.base.Optional<Checksum> checksum,
115115
String canonicalId,
116116
Path destination,
@@ -154,7 +154,7 @@ public void download(
154154
eventHandler.handle(
155155
Event.warn("Remote Cache: " + Utils.grpcAwareErrorMessage(e, verboseFailures)));
156156
fallbackDownloader.download(
157-
urls, authHeaders, checksum, canonicalId, destination, eventHandler, clientEnv, type);
157+
urls, credentials, checksum, canonicalId, destination, eventHandler, clientEnv, type);
158158
}
159159
}
160160

src/test/java/com/google/devtools/build/lib/bazel/repository/downloader/HttpConnectorMultiplexerTest.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.common.base.Optional;
3333
import com.google.common.collect.ImmutableList;
3434
import com.google.common.collect.ImmutableMap;
35+
import com.google.devtools.build.lib.authandtls.StaticCredentials;
3536
import com.google.devtools.build.lib.bazel.repository.cache.RepositoryCache.KeyType;
3637
import com.google.devtools.build.lib.bazel.repository.downloader.RetryingInputStream.Reconnector;
3738
import com.google.devtools.build.lib.events.EventHandler;
@@ -163,7 +164,8 @@ public void testHeaderComputationFunction() throws Exception {
163164
ImmutableMap.of("Authentication", ImmutableList.of("Zm9vOmZvb3NlY3JldA==")));
164165

165166
Function<URL, ImmutableMap<String, List<String>>> headerFunction =
166-
HttpConnectorMultiplexer.getHeaderFunction(baseHeaders, additionalHeaders);
167+
HttpConnectorMultiplexer.getHeaderFunction(
168+
baseHeaders, new StaticCredentials(additionalHeaders));
167169

168170
// Unreleated URL
169171
assertThat(headerFunction.apply(new URL("http://example.org/some/path/file.txt")))
@@ -215,7 +217,8 @@ public void testHeaderComputationFunction() throws Exception {
215217
ImmutableMap<String, List<String>> annonAuth =
216218
ImmutableMap.of("Authentication", ImmutableList.of("YW5vbnltb3VzOmZvb0BleGFtcGxlLm9yZw=="));
217219
Function<URL, ImmutableMap<String, List<String>>> combinedHeaders =
218-
HttpConnectorMultiplexer.getHeaderFunction(annonAuth, additionalHeaders);
220+
HttpConnectorMultiplexer.getHeaderFunction(
221+
annonAuth, new StaticCredentials(additionalHeaders));
219222
assertThat(combinedHeaders.apply(new URL("http://hosting.example.com/user/foo/file.txt")))
220223
.containsExactly("Authentication", ImmutableList.of("Zm9vOmZvb3NlY3JldA=="));
221224
assertThat(combinedHeaders.apply(new URL("http://unreleated.example.org/user/foo/file.txt")))

0 commit comments

Comments
 (0)