From ef11a0849e2fe23d902ce0cd17832f1ef44e7ba3 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Thu, 24 Apr 2025 23:06:03 -0700 Subject: [PATCH] Fix accidentally introduced Docker credential issues Attempt to fix a few issues that were accidentally introduced by missing some code from the original pull-request. See gh-45269 --- .../buildpack/platform/build/Builder.java | 12 ++----- .../DockerRegistryConfigAuthentication.java | 2 +- .../platform/build/BuilderTests.java | 35 ------------------- ...ckerRegistryConfigAuthenticationTests.java | 8 +++++ 4 files changed, 11 insertions(+), 46 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java index 2544de9ec8d..3d3b81ebfb1 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java @@ -145,9 +145,8 @@ public class Builder { Assert.notNull(request, "'request' must not be null"); this.log.start(request); validateBindings(request.getBindings()); - String domain = request.getBuilder().getDomain(); PullPolicy pullPolicy = request.getPullPolicy(); - ImageFetcher imageFetcher = new ImageFetcher(domain, this.dockerConfiguration.builderRegistryAuthentication(), + ImageFetcher imageFetcher = new ImageFetcher(this.dockerConfiguration.builderRegistryAuthentication(), pullPolicy, request.getImagePlatform()); Image builderImage = imageFetcher.fetchImage(ImageType.BUILDER, request.getBuilder()); BuilderMetadata builderMetadata = BuilderMetadata.fromImage(builderImage); @@ -260,17 +259,14 @@ public class Builder { */ private class ImageFetcher { - private final String domain; - private final DockerRegistryAuthentication registryAuthentication; private final PullPolicy pullPolicy; private ImagePlatform defaultPlatform; - ImageFetcher(String domain, DockerRegistryAuthentication registryAuthentication, PullPolicy pullPolicy, + ImageFetcher(DockerRegistryAuthentication registryAuthentication, PullPolicy pullPolicy, ImagePlatform platform) { - this.domain = domain; this.registryAuthentication = registryAuthentication; this.pullPolicy = pullPolicy; this.defaultPlatform = platform; @@ -279,10 +275,6 @@ public class Builder { Image fetchImage(ImageType type, ImageReference reference) throws IOException { Assert.notNull(type, "'type' must not be null"); Assert.notNull(reference, "'reference' must not be null"); - String authHeader = authHeader(this.registryAuthentication, reference); - Assert.state(authHeader == null || reference.getDomain().equals(this.domain), - () -> String.format("%s '%s' must be pulled from the '%s' authenticated registry", - StringUtils.capitalize(type.getDescription()), reference, this.domain)); if (this.pullPolicy == PullPolicy.ALWAYS) { return checkPlatformMismatch(pullImage(reference, type), reference); } 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 04aad1f956a..020658c6d71 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 @@ -42,7 +42,7 @@ class DockerRegistryConfigAuthentication implements DockerRegistryAuthentication private static final String INDEX_URL = "https://index.docker.io/v1/"; - private static Map credentialFromHelperCache = new ConcurrentHashMap<>(); + static Map credentialFromHelperCache = new ConcurrentHashMap<>(); private final DockerRegistryAuthentication fallback; diff --git a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java index 1260fff919c..13169ebf2d2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java @@ -445,41 +445,6 @@ class BuilderTests { .withMessage("Builder lifecycle 'creator' failed with status code 9"); } - @Test - void buildWhenDetectedRunImageInDifferentAuthenticatedRegistryThrowsException() throws Exception { - TestPrintStream out = new TestPrintStream(); - DockerApi docker = mockDockerApi(); - Image builderImage = loadImage("image-with-run-image-different-registry.json"); - DockerRegistryAuthentication builderToken = DockerRegistryAuthentication.token("builder token"); - BuilderDockerConfiguration dockerConfiguration = new BuilderDockerConfiguration() - .withBuilderRegistryAuthentication(builderToken); - ImageReference builderImageReference = DEFAULT_BUILDER; - given(docker.image().pull(eq(builderImageReference), any(), any(), regAuthEq(builderToken))) - .willAnswer(withPulledImage(builderImage)); - Builder builder = new Builder(BuildLog.to(out), docker, dockerConfiguration); - BuildRequest request = getTestRequest(); - assertThatIllegalStateException().isThrownBy(() -> builder.build(request)) - .withMessage( - "Run image 'example.com/custom/run:latest' must be pulled from the 'docker.io' authenticated registry"); - } - - @Test - void buildWhenRequestedRunImageInDifferentAuthenticatedRegistryThrowsException() throws Exception { - TestPrintStream out = new TestPrintStream(); - DockerApi docker = mockDockerApi(); - Image builderImage = loadImage("image.json"); - DockerRegistryAuthentication builderToken = DockerRegistryAuthentication.token("builder token"); - BuilderDockerConfiguration dockerConfiguration = new BuilderDockerConfiguration() - .withBuilderRegistryAuthentication(builderToken); - given(docker.image().pull(eq(DEFAULT_BUILDER), any(), any(), regAuthEq(builderToken))) - .willAnswer(withPulledImage(builderImage)); - Builder builder = new Builder(BuildLog.to(out), docker, dockerConfiguration); - BuildRequest request = getTestRequest().withRunImage(ImageReference.of("example.com/custom/run:latest")); - assertThatIllegalStateException().isThrownBy(() -> builder.build(request)) - .withMessage( - "Run image 'example.com/custom/run:latest' must be pulled from the 'docker.io' authenticated registry"); - } - @Test void buildWhenRequestedBuildpackNotInBuilderThrowsException() throws Exception { TestPrintStream out = new TestPrintStream(); 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 7d551bad022..749aabc89fe 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 @@ -25,6 +25,7 @@ import java.util.LinkedHashMap; import java.util.Map; import com.fasterxml.jackson.core.type.TypeReference; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -54,6 +55,11 @@ class DockerRegistryConfigAuthenticationTests { private Map credentialHelpers = new HashMap<>(); + @BeforeEach + void cleanup() { + DockerRegistryConfigAuthentication.credentialFromHelperCache.clear(); + } + @WithResource(name = "config.json", content = """ { "auths": { @@ -310,6 +316,8 @@ class DockerRegistryConfigAuthenticationTests { this.environment.put("DOCKER_CONFIG", directory.toString()); ImageReference imageReference = ImageReference.of("gcr.io/ubuntu:latest"); 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. assertThat(decode(authHeader)).hasSize(4) .containsEntry("serveraddress", "") .containsEntry("username", "")