Skip to content

Commit

Permalink
Enforce builder and run images in the same registry
Browse files Browse the repository at this point in the history
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
  • Loading branch information
scottfrederick committed Jan 12, 2021
1 parent a6a7c06 commit a9e711e
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 2 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -116,6 +116,7 @@ private BuildRequest determineRunImage(BuildRequest request, Image builderImage,
ImageReference runImage = getRunImageReferenceForStack(builderStack);
request = request.withRunImage(runImage);
}
assertImageRegistriesMatch(request);
Image runImage = getImage(request, ImageType.RUNNER);
assertStackIdsMatch(runImage, builderImage);
return request;
Expand Down Expand Up @@ -172,6 +173,14 @@ private String getPublishAuthHeader() {
? this.dockerConfiguration.getPublishRegistryAuthentication().getAuthHeader() : null;
}

private void assertImageRegistriesMatch(BuildRequest request) {
if (getBuilderAuthHeader() != null) {
Assert.state(request.getRunImage().getDomain().equals(request.getBuilder().getDomain()),
"Builder image '" + request.getBuilder() + "' and run image '" + request.getRunImage()
+ "' must be pulled from the same authenticated registry");
}
}

private void assertStackIdsMatch(Image runImage, Image builderImage) {
StackId runImageStackId = StackId.fromImage(runImage);
StackId builderImageStackId = StackId.fromImage(builderImage);
Expand Down
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2020 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -308,6 +308,42 @@ void buildWhenBuilderReturnsErrorThrowsException() throws Exception {
.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");
DockerConfiguration dockerConfiguration = new DockerConfiguration()
.withBuilderRegistryTokenAuthentication("builder token");
given(docker.image().pull(eq(ImageReference.of(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)), any(),
eq(dockerConfiguration.getBuilderRegistryAuthentication().getAuthHeader())))
.willAnswer(withPulledImage(builderImage));
Builder builder = new Builder(BuildLog.to(out), docker, dockerConfiguration);
BuildRequest request = getTestRequest();
assertThatIllegalStateException().isThrownBy(() -> builder.build(request))
.withMessageContaining(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)
.withMessageContaining("example.com/custom/run:latest")
.withMessageContaining("must be pulled from the same authenticated registry");
}

@Test
void buildWhenRequestedRunImageInDifferentAuthenticatedRegistryThrowsException() throws Exception {
TestPrintStream out = new TestPrintStream();
DockerApi docker = mockDockerApi();
Image builderImage = loadImage("image.json");
DockerConfiguration dockerConfiguration = new DockerConfiguration()
.withBuilderRegistryTokenAuthentication("builder token");
given(docker.image().pull(eq(ImageReference.of(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)), any(),
eq(dockerConfiguration.getBuilderRegistryAuthentication().getAuthHeader())))
.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))
.withMessageContaining(BuildRequest.DEFAULT_BUILDER_IMAGE_NAME)
.withMessageContaining("example.com/custom/run:latest")
.withMessageContaining("must be pulled from the same authenticated registry");
}

private DockerApi mockDockerApi() throws IOException {
ContainerApi containerApi = mock(ContainerApi.class);
ContainerReference reference = ContainerReference.of("container-ref");
Expand Down

0 comments on commit a9e711e

Please sign in to comment.