Skip to content

Commit a9e711e

Browse files
Enforce builder and run images in the same registry
Previously, when an authenticated Docker builder registry was configured in the Maven or Gradle plugin and the builder and run images specified different registries, the authentication credentials would be sent to both registries. This could cause confusion if both registries don't recognize the same credentials. This commit enforces that both images are in the same registry when authentication is configured. Fixes gh-24552
1 parent a6a7c06 commit a9e711e

File tree

3 files changed

+179
-2
lines changed

3 files changed

+179
-2
lines changed

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/build/Builder.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -116,6 +116,7 @@ private BuildRequest determineRunImage(BuildRequest request, Image builderImage,
116116
ImageReference runImage = getRunImageReferenceForStack(builderStack);
117117
request = request.withRunImage(runImage);
118118
}
119+
assertImageRegistriesMatch(request);
119120
Image runImage = getImage(request, ImageType.RUNNER);
120121
assertStackIdsMatch(runImage, builderImage);
121122
return request;
@@ -172,6 +173,14 @@ private String getPublishAuthHeader() {
172173
? this.dockerConfiguration.getPublishRegistryAuthentication().getAuthHeader() : null;
173174
}
174175

176+
private void assertImageRegistriesMatch(BuildRequest request) {
177+
if (getBuilderAuthHeader() != null) {
178+
Assert.state(request.getRunImage().getDomain().equals(request.getBuilder().getDomain()),
179+
"Builder image '" + request.getBuilder() + "' and run image '" + request.getRunImage()
180+
+ "' must be pulled from the same authenticated registry");
181+
}
182+
}
183+
175184
private void assertStackIdsMatch(Image runImage, Image builderImage) {
176185
StackId runImageStackId = StackId.fromImage(runImage);
177186
StackId builderImageStackId = StackId.fromImage(builderImage);

spring-boot-project/spring-boot-tools/spring-boot-buildpack-platform/src/test/java/org/springframework/boot/buildpack/platform/build/BuilderTests.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -308,6 +308,42 @@ void buildWhenBuilderReturnsErrorThrowsException() throws Exception {
308308
.withMessage("Builder lifecycle 'creator' failed with status code 9");
309309
}
310310

311+
@Test
312+
void buildWhenDetectedRunImageInDifferentAuthenticatedRegistryThrowsException() throws Exception {
313+
TestPrintStream out = new TestPrintStream();
314+
DockerApi docker = mockDockerApi();
315+
Image builderImage = loadImage("image-with-run-image-different-registry.json");
316+
DockerConfiguration dockerConfiguration = new DockerConfiguration()
317+
.withBuilderRegistryTokenAuthentication("builder token");
318+
given(docker.image().pull(eq(ImageReference.of(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)), any(),
319+
eq(dockerConfiguration.getBuilderRegistryAuthentication().getAuthHeader())))
320+
.willAnswer(withPulledImage(builderImage));
321+
Builder builder = new Builder(BuildLog.to(out), docker, dockerConfiguration);
322+
BuildRequest request = getTestRequest();
323+
assertThatIllegalStateException().isThrownBy(() -> builder.build(request))
324+
.withMessageContaining(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)
325+
.withMessageContaining("example.com/custom/run:latest")
326+
.withMessageContaining("must be pulled from the same authenticated registry");
327+
}
328+
329+
@Test
330+
void buildWhenRequestedRunImageInDifferentAuthenticatedRegistryThrowsException() throws Exception {
331+
TestPrintStream out = new TestPrintStream();
332+
DockerApi docker = mockDockerApi();
333+
Image builderImage = loadImage("image.json");
334+
DockerConfiguration dockerConfiguration = new DockerConfiguration()
335+
.withBuilderRegistryTokenAuthentication("builder token");
336+
given(docker.image().pull(eq(ImageReference.of(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)), any(),
337+
eq(dockerConfiguration.getBuilderRegistryAuthentication().getAuthHeader())))
338+
.willAnswer(withPulledImage(builderImage));
339+
Builder builder = new Builder(BuildLog.to(out), docker, dockerConfiguration);
340+
BuildRequest request = getTestRequest().withRunImage(ImageReference.of("example.com/custom/run:latest"));
341+
assertThatIllegalStateException().isThrownBy(() -> builder.build(request))
342+
.withMessageContaining(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)
343+
.withMessageContaining("example.com/custom/run:latest")
344+
.withMessageContaining("must be pulled from the same authenticated registry");
345+
}
346+
311347
private DockerApi mockDockerApi() throws IOException {
312348
ContainerApi containerApi = mock(ContainerApi.class);
313349
ContainerReference reference = ContainerReference.of("container-ref");

0 commit comments

Comments
 (0)