Skip to content

Commit

Permalink
Make allowInsecureRegistries follow Docker semantics (#733)
Browse files Browse the repository at this point in the history
  • Loading branch information
chanseokoh authored Aug 1, 2018
1 parent df08f66 commit d476d31
Show file tree
Hide file tree
Showing 4 changed files with 206 additions and 108 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.GeneralSecurityException;
import java.util.function.Function;
import javax.annotation.Nullable;
import javax.net.ssl.SSLPeerUnverifiedException;
Expand All @@ -52,6 +53,10 @@ class RegistryEndpointCaller<T> {

private static final String DEFAULT_PROTOCOL = "https";

private static boolean isHttpsProtocol(URL url) {
return "https".equals(url.getProtocol());
}

private final JibLogger logger;
private final URL initialRequestUrl;
private final String userAgent;
Expand Down Expand Up @@ -132,7 +137,52 @@ class RegistryEndpointCaller<T> {
*/
@Nullable
T call() throws IOException, RegistryException {
return call(initialRequestUrl);
return callWithAllowInsecureRegistryHandling(initialRequestUrl);
}

@Nullable
private T callWithAllowInsecureRegistryHandling(URL url) throws IOException, RegistryException {
if (!isHttpsProtocol(url) && !allowInsecureRegistries) {
throw new InsecureRegistryException(url);
}

try {
return call(url, connectionFactory);

} catch (SSLPeerUnverifiedException ex) {
return handleUnverifiableServerException(url);
}
}

@Nullable
private T handleUnverifiableServerException(URL url) throws IOException, RegistryException {
if (!allowInsecureRegistries) {
throw new InsecureRegistryException(url);
}

try {
return call(url, getInsecureConnectionFactory());

} catch (SSLPeerUnverifiedException | HttpHostConnectException ex) {
// Try HTTP as a last resort.
GenericUrl httpUrl = new GenericUrl(url);
httpUrl.setScheme("http");
logger.warn(
"Failed to connect to " + url + " over HTTPS. Attempting again with HTTP: " + httpUrl);
return call(httpUrl.toURL(), connectionFactory);
}
}

private Function<URL, Connection> getInsecureConnectionFactory() throws RegistryException {
try {
if (insecureConnectionFactory == null) {
insecureConnectionFactory = Connection.getInsecureConnectionFactory();
}
return insecureConnectionFactory;

} catch (GeneralSecurityException ex) {
throw new RegistryException("cannot turn off TLS peer verification", ex);
}
}

/**
Expand All @@ -143,15 +193,11 @@ T call() throws IOException, RegistryException {
* @throws IOException for most I/O exceptions when making the request
* @throws RegistryException for known exceptions when interacting with the registry
*/
@VisibleForTesting
@Nullable
T call(URL url) throws IOException, RegistryException {
boolean isHttpProtocol = "http".equals(url.getProtocol());
if (!allowInsecureRegistries && isHttpProtocol) {
throw new InsecureRegistryException(url);
}
private T call(URL url, Function<URL, Connection> connectionFactory)
throws IOException, RegistryException {
// Only sends authorization if using HTTPS or explicitly forcing over HTTP.
boolean sendCredentials = !isHttpProtocol || Boolean.getBoolean("sendCredentialsOverHttp");
boolean sendCredentials = isHttpsProtocol(url) || Boolean.getBoolean("sendCredentialsOverHttp");

try (Connection connection = connectionFactory.apply(url)) {
Request.Builder requestBuilder =
Expand Down Expand Up @@ -218,27 +264,13 @@ T call(URL url) throws IOException, RegistryException {
|| httpResponseException.getStatusCode() == STATUS_CODE_PERMANENT_REDIRECT) {
// 'Location' header can be relative or absolute.
URL redirectLocation = new URL(url, httpResponseException.getHeaders().getLocation());
return call(redirectLocation);
return callWithAllowInsecureRegistryHandling(redirectLocation);

} else {
// Unknown
throw httpResponseException;
}
}

} catch (HttpHostConnectException | SSLPeerUnverifiedException ex) {
// Tries to call with HTTP protocol if HTTPS failed to connect.
// Note that this will not succeed if 'allowInsecureRegistries' is false.
if ("https".equals(url.getProtocol())) {
GenericUrl httpUrl = new GenericUrl(url);
httpUrl.setScheme("http");
logger.warn(
"Failed to connect to " + url + " over HTTPS. Attempting again with HTTP: " + httpUrl);
return call(httpUrl.toURL());
}

throw ex;

} catch (NoHttpResponseException ex) {
throw new RegistryNoResponseException(ex);
}
Expand Down
Loading

0 comments on commit d476d31

Please sign in to comment.