diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java index 020658c6d71d..5d1495dc744d 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthentication.java +++ b/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 @@ 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 DockerRegistryConfigAuthentication(DockerRegistryAuthentication fallback, BiConsumer 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 @@ private DockerRegistryAuthentication getAuthentication(Credential credentialsFro } 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 @@ private Credential computeCredentialsFromHelper(String serverUrl) { 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 @@ private Credential computeCredentialsFromHelper(String serverUrl) { 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 getAuthConfigEntry(String serverUrl) { + private Map.Entry getAuthConfigEntry(String serverUrl) { for (Map.Entry candidate : this.dockerConfig.getAuths().entrySet()) { if (candidate.getKey().equals(serverUrl) || candidate.getKey().endsWith("://" + serverUrl)) { return candidate; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthenticationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthenticationTests.java index 749aabc89fed..a60e04f184ec 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/docker/configuration/DockerRegistryConfigAuthenticationTests.java +++ b/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.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 { private final Map helperExceptions = new LinkedHashMap<>(); - private Map credentialHelpers = new HashMap<>(); + private final Map credentialHelpers = new HashMap<>(); @BeforeEach void cleanup() { @@ -315,6 +318,7 @@ void getAuthHeaderWhenEmptyCredHelperReturnsFallbackAndDoesNotUseCredStore(@Reso 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 @@ void getAuthHeaderWhenEmptyCredHelperReturnsFallbackAndDoesNotUseCredStore(@Reso .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) {