Browse Source

Merge pull request #45292 from nosan

* pr/45292:
  Align DockerRegistryConfigAuthentication with Docker CLI

Closes gh-45292
pull/45345/head
Moritz Halbritter 9 months ago
parent
commit
75fe588ef2
  1. 16
      spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java
  2. 25
      spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthenticationTests.java

16
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java

@ -16,9 +16,7 @@ @@ -16,9 +16,7 @@
package org.springframework.boot.buildpack.platform.docker.configuration;
import java.io.IOException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
import java.util.function.Function;
@ -55,7 +53,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication @@ -55,7 +53,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication
DockerRegistryConfigAuthentication(DockerRegistryAuthentication fallback,
BiConsumer<String, Exception> credentialHelperExceptionHandler) {
this(fallback, credentialHelperExceptionHandler, Environment.SYSTEM,
(helper) -> new CredentialHelper("docker-credential-" + helper.trim()));
(helper) -> new CredentialHelper("docker-credential-" + helper));
}
DockerRegistryConfigAuthentication(DockerRegistryAuthentication fallback,
@ -106,14 +104,14 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication @@ -106,14 +104,14 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication
}
String username = credentialsFromHelper.getUsername();
String password = credentialsFromHelper.getSecret();
String serverAddress = (credentialsFromHelper.getServerUrl() != null
&& !credentialsFromHelper.getServerUrl().isEmpty()) ? credentialsFromHelper.getServerUrl() : serverUrl;
String serverAddress = (StringUtils.hasLength(credentialsFromHelper.getServerUrl()))
? credentialsFromHelper.getServerUrl() : serverUrl;
String email = (authConfig != null) ? authConfig.getEmail() : null;
return DockerRegistryAuthentication.user(username, password, serverAddress, email);
}
private Credential getCredentialsFromHelper(String serverUrl) {
return (StringUtils.hasText(serverUrl))
return StringUtils.hasLength(serverUrl)
? credentialFromHelperCache.computeIfAbsent(serverUrl, this::computeCredentialsFromHelper) : null;
}
@ -123,7 +121,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication @@ -123,7 +121,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication
try {
return credentialHelper.get(serverUrl);
}
catch (IOException ex) {
catch (Exception ex) {
String message = "Error retrieving credentials for '%s' due to: %s".formatted(serverUrl,
ex.getMessage());
this.credentialHelperExceptionHandler.accept(message, ex);
@ -134,10 +132,10 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication @@ -134,10 +132,10 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication
private CredentialHelper getCredentialHelper(String serverUrl) {
String name = this.dockerConfig.getCredHelpers().getOrDefault(serverUrl, this.dockerConfig.getCredsStore());
return (name != null) ? this.credentialHelperFactory.apply(name.trim()) : null;
return (StringUtils.hasLength(name)) ? this.credentialHelperFactory.apply(name) : null;
}
private Entry<String, Auth> getAuthConfigEntry(String serverUrl) {
private Map.Entry<String, Auth> getAuthConfigEntry(String serverUrl) {
for (Map.Entry<String, Auth> candidate : this.dockerConfig.getAuths().entrySet()) {
if (candidate.getKey().equals(serverUrl) || candidate.getKey().endsWith("://" + serverUrl)) {
return candidate;

25
spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthenticationTests.java

@ -37,8 +37,11 @@ import org.springframework.boot.testsupport.system.OutputCaptureExtension; @@ -37,8 +37,11 @@ import org.springframework.boot.testsupport.system.OutputCaptureExtension;
import org.springframework.core.io.ClassPathResource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
/**
* Tests for {@link DockerRegistryConfigAuthentication}.
@ -53,7 +56,7 @@ class DockerRegistryConfigAuthenticationTests { @@ -53,7 +56,7 @@ class DockerRegistryConfigAuthenticationTests {
private final Map<String, Exception> helperExceptions = new LinkedHashMap<>();
private Map<String, CredentialHelper> credentialHelpers = new HashMap<>();
private final Map<String, CredentialHelper> credentialHelpers = new HashMap<>();
@BeforeEach
void cleanup() {
@ -315,6 +318,7 @@ class DockerRegistryConfigAuthenticationTests { @@ -315,6 +318,7 @@ class DockerRegistryConfigAuthenticationTests {
throws Exception {
this.environment.put("DOCKER_CONFIG", directory.toString());
ImageReference imageReference = ImageReference.of("gcr.io/ubuntu:latest");
CredentialHelper desktopHelper = mockHelper("desktop");
String authHeader = getAuthHeader(imageReference, DockerRegistryAuthentication.EMPTY_USER);
// The Docker CLI appears to prioritize the credential helper over the
// credential store, even when the helper is empty.
@ -323,6 +327,25 @@ class DockerRegistryConfigAuthenticationTests { @@ -323,6 +327,25 @@ class DockerRegistryConfigAuthenticationTests {
.containsEntry("username", "")
.containsEntry("password", "")
.containsEntry("email", "");
then(desktopHelper).should(never()).get(any(String.class));
}
@WithResource(name = "config.json", content = """
{
"credsStore": "desktop"
}
""")
@Test
void getAuthHeaderReturnsFallbackWhenImageReferenceNull(@ResourcesRoot Path directory) throws Exception {
this.environment.put("DOCKER_CONFIG", directory.toString());
CredentialHelper desktopHelper = mockHelper("desktop");
String authHeader = getAuthHeader(null, DockerRegistryAuthentication.EMPTY_USER);
assertThat(decode(authHeader)).hasSize(4)
.containsEntry("serveraddress", "")
.containsEntry("username", "")
.containsEntry("password", "")
.containsEntry("email", "");
then(desktopHelper).should(never()).get(any(String.class));
}
private String getAuthHeader(ImageReference imageReference) {

Loading…
Cancel
Save