Add support for untrusted CNB builders
A `trustBuilder` configuration option has been added to the Maven and Gradle CNB integration image building goal and task. A known set of builders published by Paketo, Heroku, and Google are trusted by default, all other builders are untrusted by default. Closes gh-41352
This commit is contained in:
@@ -68,6 +68,8 @@ class BuildImageTests extends AbstractArchiveIntegrationTests {
|
||||
assertThat(original).doesNotExist();
|
||||
assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("docker.io/library/build-image:0.0.1.BUILD-SNAPSHOT")
|
||||
.contains("Running detector")
|
||||
.contains("Running builder")
|
||||
.contains("---> Test Info buildpack building")
|
||||
.contains("---> Test Info buildpack done")
|
||||
.contains("Successfully built image");
|
||||
@@ -88,6 +90,8 @@ class BuildImageTests extends AbstractArchiveIntegrationTests {
|
||||
assertThat(original).doesNotExist();
|
||||
assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("docker.io/library/build-image-cmd-line:0.0.1.BUILD-SNAPSHOT")
|
||||
.contains("Running detector")
|
||||
.contains("Running builder")
|
||||
.contains("---> Test Info buildpack building")
|
||||
.contains("---> Test Info buildpack done")
|
||||
.contains("Successfully built image");
|
||||
@@ -248,12 +252,14 @@ class BuildImageTests extends AbstractArchiveIntegrationTests {
|
||||
.systemProperty("spring-boot.build-image.pullPolicy", "IF_NOT_PRESENT")
|
||||
.systemProperty("spring-boot.build-image.imageName", "example.com/test/cmd-property-name:v1")
|
||||
.systemProperty("spring-boot.build-image.builder", "ghcr.io/spring-io/spring-boot-cnb-test-builder:0.0.1")
|
||||
.systemProperty("spring-boot.build-image.trustBuilder", "true")
|
||||
.systemProperty("spring-boot.build-image.runImage", "paketobuildpacks/run-jammy-tiny")
|
||||
.systemProperty("spring-boot.build-image.createdDate", "2020-07-01T12:34:56Z")
|
||||
.systemProperty("spring-boot.build-image.applicationDirectory", "/application")
|
||||
.execute((project) -> {
|
||||
assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("example.com/test/cmd-property-name:v1")
|
||||
.contains("Running creator")
|
||||
.contains("---> Test Info buildpack building")
|
||||
.contains("---> Test Info buildpack done")
|
||||
.contains("Successfully built image");
|
||||
@@ -279,6 +285,22 @@ class BuildImageTests extends AbstractArchiveIntegrationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void whenBuildImageIsInvokedWithTrustBuilder(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("dockerTest", "build-image-trust-builder")
|
||||
.goals("package")
|
||||
.systemProperty("spring-boot.build-image.pullPolicy", "IF_NOT_PRESENT")
|
||||
.execute((project) -> {
|
||||
assertThat(buildLog(project)).contains("Building image")
|
||||
.contains("docker.io/library/build-image-v2-trust-builder:0.0.1.BUILD-SNAPSHOT")
|
||||
.contains("Running creator")
|
||||
.contains("---> Test Info buildpack building")
|
||||
.contains("---> Test Info buildpack done")
|
||||
.contains("Successfully built image");
|
||||
removeImage("docker.io/library/build-image-v2-trust-builder", "0.0.1.BUILD-SNAPSHOT");
|
||||
});
|
||||
}
|
||||
|
||||
@TestTemplate
|
||||
void whenBuildImageIsInvokedWithEmptyEnvEntry(MavenBuild mavenBuild) {
|
||||
mavenBuild.project("dockerTest", "build-image-empty-env-entry")
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.boot.maven.it</groupId>
|
||||
<artifactId>build-image-v2-trust-builder</artifactId>
|
||||
<version>0.0.1.BUILD-SNAPSHOT</version>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>@java.version@</maven.compiler.source>
|
||||
<maven.compiler.target>@java.version@</maven.compiler.target>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>@project.groupId@</groupId>
|
||||
<artifactId>@project.artifactId@</artifactId>
|
||||
<version>@project.version@</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build-image-no-fork</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<image>
|
||||
<builder>ghcr.io/spring-io/spring-boot-cnb-test-builder:0.0.1</builder>
|
||||
<trustBuilder>true</trustBuilder>
|
||||
</image>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2012-2024 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.test;
|
||||
|
||||
public class SampleApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.out.println("Launched");
|
||||
synchronized(args) {
|
||||
args.wait(); // Prevent exit
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -134,9 +134,14 @@ The following table summarizes the available parameters and their default values
|
||||
|
||||
| `builder` +
|
||||
(`spring-boot.build-image.builder`)
|
||||
| Name of the Builder image to use.
|
||||
| Name of the builder image to use.
|
||||
| `paketobuildpacks/builder-jammy-tiny:latest`
|
||||
|
||||
| `trustBuilder` +
|
||||
(`spring-boot.build-image.trustBuilder`)
|
||||
| Whether to treat the builder as https://buildpacks.io/docs/for-platform-operators/how-to/integrate-ci/pack/concepts/trusted_builders/#what-is-a-trusted-builder[trusted].
|
||||
| `true` if the builder is one of `paketobuildpacks/builder-jammy-tiny`, `paketobuildpacks/builder-jammy-base`, `paketobuildpacks/builder-jammy-full`, `paketobuildpacks/builder-jammy-buildpackless-tiny`, `paketobuildpacks/builder-jammy-buildpackless-base`, `paketobuildpacks/builder-jammy-buildpackless-full`, `gcr.io/buildpacks/builder`, `heroku/builder`; false otherwise.
|
||||
|
||||
| `runImage` +
|
||||
(`spring-boot.build-image.runImage`)
|
||||
| Name of the run image to use.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -118,6 +118,13 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
|
||||
@Parameter(property = "spring-boot.build-image.builder", readonly = true)
|
||||
String imageBuilder;
|
||||
|
||||
/**
|
||||
* Alias for {@link Image#trustBuilder} to support configuration through command-line
|
||||
* property.
|
||||
*/
|
||||
@Parameter(property = "spring-boot.build-image.trustBuilder", readonly = true)
|
||||
Boolean trustBuilder;
|
||||
|
||||
/**
|
||||
* Alias for {@link Image#runImage} to support configuration through command-line
|
||||
* property.
|
||||
@@ -267,6 +274,9 @@ public abstract class BuildImageMojo extends AbstractPackagerMojo {
|
||||
if (image.builder == null && this.imageBuilder != null) {
|
||||
image.setBuilder(this.imageBuilder);
|
||||
}
|
||||
if (image.trustBuilder == null && this.trustBuilder != null) {
|
||||
image.setTrustBuilder(this.trustBuilder);
|
||||
}
|
||||
if (image.runImage == null && this.runImage != null) {
|
||||
image.setRunImage(this.runImage);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 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.
|
||||
@@ -49,6 +49,8 @@ public class Image {
|
||||
|
||||
String builder;
|
||||
|
||||
Boolean trustBuilder;
|
||||
|
||||
String runImage;
|
||||
|
||||
Map<String, String> env;
|
||||
@@ -105,6 +107,18 @@ public class Image {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the builder should be treated as trusted.
|
||||
* @return {@code true} if the builder should be treated as trusted
|
||||
*/
|
||||
public Boolean getTrustBuilder() {
|
||||
return this.trustBuilder;
|
||||
}
|
||||
|
||||
void setTrustBuilder(Boolean trustBuilder) {
|
||||
this.trustBuilder = trustBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the run image to use to create the image.
|
||||
* @return the builder image name
|
||||
@@ -221,6 +235,9 @@ public class Image {
|
||||
if (StringUtils.hasText(this.builder)) {
|
||||
request = request.withBuilder(ImageReference.of(this.builder));
|
||||
}
|
||||
if (this.trustBuilder != null) {
|
||||
request = request.withTrustBuilder(this.trustBuilder);
|
||||
}
|
||||
if (StringUtils.hasText(this.runImage)) {
|
||||
request = request.withRunImage(ImageReference.of(this.runImage));
|
||||
}
|
||||
|
||||
@@ -70,11 +70,13 @@ class ImageTests {
|
||||
BuildRequest request = new Image().getBuildRequest(createArtifact(), mockApplicationContent());
|
||||
assertThat(request.getName()).hasToString("docker.io/library/my-app:0.0.1-SNAPSHOT");
|
||||
assertThat(request.getBuilder().toString()).contains("paketobuildpacks/builder-jammy-tiny");
|
||||
assertThat(request.isTrustBuilder()).isTrue();
|
||||
assertThat(request.getRunImage()).isNull();
|
||||
assertThat(request.getEnv()).isEmpty();
|
||||
assertThat(request.isCleanCache()).isFalse();
|
||||
assertThat(request.isVerboseLogging()).isFalse();
|
||||
assertThat(request.getPullPolicy()).isEqualTo(PullPolicy.ALWAYS);
|
||||
assertThat(request.isPublish()).isFalse();
|
||||
assertThat(request.getBuildpacks()).isEmpty();
|
||||
assertThat(request.getBindings()).isEmpty();
|
||||
assertThat(request.getNetwork()).isNull();
|
||||
@@ -86,6 +88,26 @@ class ImageTests {
|
||||
image.builder = "springboot/builder:2.2.x";
|
||||
BuildRequest request = image.getBuildRequest(createArtifact(), mockApplicationContent());
|
||||
assertThat(request.getBuilder()).hasToString("docker.io/springboot/builder:2.2.x");
|
||||
assertThat(request.isTrustBuilder()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBuildRequestWhenHasBuilderAndTrustBuilderUsesBuilderAndTrustBuilder() {
|
||||
Image image = new Image();
|
||||
image.builder = "springboot/builder:2.2.x";
|
||||
image.trustBuilder = true;
|
||||
BuildRequest request = image.getBuildRequest(createArtifact(), mockApplicationContent());
|
||||
assertThat(request.getBuilder()).hasToString("docker.io/springboot/builder:2.2.x");
|
||||
assertThat(request.isTrustBuilder()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBuildRequestWhenHasDefaultBuilderAndTrustBuilderUsesTrustBuilder() {
|
||||
Image image = new Image();
|
||||
image.trustBuilder = false;
|
||||
BuildRequest request = image.getBuildRequest(createArtifact(), mockApplicationContent());
|
||||
assertThat(request.getBuilder().toString()).contains("paketobuildpacks/builder-jammy-tiny");
|
||||
assertThat(request.isTrustBuilder()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user