Skip to content

Commit

Permalink
feature: Add the possibility to give secret to buildx build (fabric8i…
Browse files Browse the repository at this point in the history
…o#1798)

Signed-off-by: Kevin Leturc <kevinleturc@users.noreply.github.com>
  • Loading branch information
kevinleturc committed Jul 15, 2024
1 parent e980189 commit 76975c6
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 17 deletions.
2 changes: 2 additions & 0 deletions src/main/asciidoc/inc/build/_buildx.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ element defaults to `min` and the `<sbom>` element defaults to `false`.
| A value to be passed through to the `--cache-from` option of `docker buildx build`. See https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-from[docker buildx reference docs].
| *cacheTo*
| A value to be passed through to the `--cache-to` option of `docker buildx build`. See https://docs.docker.com/engine/reference/commandline/buildx_build/#cache-to[docker buildx reference docs].
| *secret*
| Two Maps, under `envs` and `files` of `<ID>VALUE</id>` elements specifying the values of https://docs.docker.com/reference/cli/docker/buildx/build/#secret[Docker Buildx secret] to give to the build as `--secret id=ID[,[env\|src]=VALUE]`.
|===

.Examples
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ public class BuildXConfiguration implements Serializable {
@Parameter
private Map<String, String> driverOpts;

/**
* Secret to expose to the build
*/
@Parameter
private SecretConfiguration secret;

public String getBuilderName() {
return builderName;
}
Expand Down Expand Up @@ -102,6 +108,10 @@ public Map<String, String> getDriverOpts() {
return driverOpts;
}

public SecretConfiguration getSecret() {
return secret;
}

public static class Builder {

private final BuildXConfiguration config = new BuildXConfiguration();
Expand Down Expand Up @@ -159,7 +169,6 @@ public Builder attestations(AttestationConfiguration attestations) {
return this;
}


public Builder cacheFrom(String cacheFrom) {
config.cacheFrom = cacheFrom;
if (cacheFrom != null) {
Expand All @@ -183,5 +192,13 @@ public Builder cacheTo(String cacheTo) {
}
return this;
}

public Builder secret(SecretConfiguration secret) {
config.secret = secret;
if (secret != null) {
isEmpty = false;
}
return this;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.fabric8.maven.docker.config;

import org.apache.maven.plugins.annotations.Parameter;

import java.io.Serializable;
import java.util.Map;

/**
* @since 15/07/24
*/
public class SecretConfiguration implements Serializable {

@Parameter
private Map<String, String> envs;

@Parameter
private Map<String, String> files;

public Map<String, String> getEnvs() {
return envs;
}

public Map<String, String> getFiles() {
return files;
}

public static class Builder {

private final SecretConfiguration config = new SecretConfiguration();
private boolean isEmpty = true;

public SecretConfiguration build() {
return isEmpty ? null : config;
}

public SecretConfiguration.Builder envs(Map<String, String> envs) {
config.envs = envs;
if (envs != null) {
isEmpty = false;
}
return this;
}

public SecretConfiguration.Builder files(Map<String, String> files) {
config.files = files;
if (files != null) {
isEmpty = false;
}
return this;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public enum ConfigKey {
BUILDX_ATTESTATION_SBOM("buildx.attestations.sbom"),
BUILDX_CACHE_FROM("buildx.cacheFrom"),
BUILDX_CACHE_TO("buildx.cacheTo"),
BUILDX_SECRET_ENVS("buildx.secret.envs", ValueCombinePolicy.Merge),
BUILDX_SECRET_FILES("buildx.secret.files", ValueCombinePolicy.Merge),
CAP_ADD,
CAP_DROP,
SYSCTLS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import io.fabric8.maven.docker.config.RestartPolicy;
import io.fabric8.maven.docker.config.RunImageConfiguration;
import io.fabric8.maven.docker.config.RunVolumeConfiguration;
import io.fabric8.maven.docker.config.SecretConfiguration;
import io.fabric8.maven.docker.config.UlimitConfig;
import io.fabric8.maven.docker.config.WaitConfiguration;
import io.fabric8.maven.docker.config.WatchImageConfiguration;
Expand Down Expand Up @@ -342,6 +343,7 @@ private BuildXConfiguration extractBuildx(BuildXConfiguration config, ValueProvi
.attestations(extractAttestations(config.getAttestations(), valueProvider))
.cacheFrom(valueProvider.getString(BUILDX_CACHE_FROM, config.getCacheFrom()))
.cacheTo(valueProvider.getString(BUILDX_CACHE_TO, config.getCacheTo()))
.secret(extractSecret(config.getSecret(), valueProvider))
.build();
}

Expand All @@ -356,6 +358,17 @@ private AttestationConfiguration extractAttestations(AttestationConfiguration co
.build();
}

private SecretConfiguration extractSecret(SecretConfiguration config, ValueProvider valueProvider) {
if (config == null) {
config = new SecretConfiguration();
}

return new SecretConfiguration.Builder()
.envs(valueProvider.getMap(BUILDX_SECRET_ENVS, config.getEnvs()))
.files(valueProvider.getMap(BUILDX_SECRET_FILES, config.getFiles()))
.build();
}

// Extract only the values of the port mapping

private List<String> extractPortValues(List<String> config, ValueProvider valueProvider) {
Expand Down
23 changes: 23 additions & 0 deletions src/main/java/io/fabric8/maven/docker/service/BuildXService.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import io.fabric8.maven.docker.config.BuildXConfiguration;
import io.fabric8.maven.docker.config.ConfigHelper;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.config.SecretConfiguration;
import io.fabric8.maven.docker.util.EnvUtil;
import io.fabric8.maven.docker.util.ImageName;
import io.fabric8.maven.docker.util.Logger;
Expand All @@ -35,6 +36,8 @@
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.Consumer;

public class BuildXService {
private static final String DOCKER = "docker";
Expand Down Expand Up @@ -190,6 +193,15 @@ protected void buildX(List<String> buildX, String builderName, BuildDirs buildDi
if (buildXConfiguration.getCacheTo() != null) {
cmdLine.add("--cache-to=" + buildXConfiguration.getCacheTo());
}
SecretConfiguration secret = buildXConfiguration.getSecret();
if (secret != null) {
if (secret.getEnvs() != null) {
secret.getEnvs().forEach(buildXSecretConsumerFor("env", cmdLine::add));
}
if (secret.getFiles() != null) {
secret.getFiles().forEach(buildXSecretConsumerFor("src", cmdLine::add));
}
}

if (buildConfiguration.squash()) {
cmdLine.add("--squash");
Expand All @@ -213,6 +225,17 @@ protected void buildX(List<String> buildX, String builderName, BuildDirs buildDi
}
}

protected BiConsumer<String, String> buildXSecretConsumerFor(String attribute, Consumer<String> cmdLineConsumer) {
return (arg0, arg1) -> {
cmdLineConsumer.accept("--secret");
String secretParameter = "id=" + arg0;
if (arg1 != null) {
secretParameter += "," + attribute + "=" + arg1;
}
cmdLineConsumer.accept(secretParameter);
};
}

protected Path getContextPath(File buildArchive) throws MojoExecutionException {
String archiveName = buildArchive.getName();
String fileName = archiveName.substring(0, archiveName.indexOf('.'));
Expand Down
57 changes: 41 additions & 16 deletions src/test/java/io/fabric8/maven/docker/BuildMojoTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import io.fabric8.maven.docker.config.BuildImageConfiguration;
import io.fabric8.maven.docker.config.BuildXConfiguration;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.docker.config.SecretConfiguration;
import io.fabric8.maven.docker.service.BuildService;
import io.fabric8.maven.docker.service.BuildXService;
import io.fabric8.maven.docker.service.ImagePullManager;
Expand Down Expand Up @@ -95,7 +96,7 @@ void buildUsingBuildx() throws IOException, MojoExecutionException {

whenMojoExecutes();

thenBuildxRun(null, null, true, null );
thenBuildxRun(null, null, true, Collections.emptyList());
}

@Test
Expand All @@ -108,7 +109,7 @@ void buildUsingConfiguredBuildx() throws IOException, MojoExecutionException {

whenMojoExecutes();

thenBuildxRun("src/docker/builder.toml", null, true, null );
thenBuildxRun("src/docker/builder.toml", null, true, Collections.emptyList());
}

@Test
Expand All @@ -126,7 +127,7 @@ void buildUsingConfiguredBuildxWithContext() throws IOException, MojoExecutionEx

whenMojoExecutes();

thenBuildxRun(null, "src/main/docker", true,null );
thenBuildxRun(null, "src/main/docker", true, Collections.emptyList());
}

@Test
Expand Down Expand Up @@ -156,7 +157,7 @@ void buildUsingBuildxWithSquash() throws IOException, MojoExecutionException {

whenMojoExecutes();

thenBuildxRun(null, null, true, "--squash");
thenBuildxRun(null, null, true, Collections.singletonList("--squash"));
}

@Test
Expand All @@ -169,7 +170,7 @@ void buildUsingBuildxWithSbom() throws IOException, MojoExecutionException {

whenMojoExecutes();

thenBuildxRun(null, null, true, "--sbom=true");
thenBuildxRun(null, null, true, Collections.singletonList("--sbom=true"));
}

@Test
Expand All @@ -182,7 +183,7 @@ void buildUsingBuildxWithMaxProvenance() throws IOException, MojoExecutionExcept

whenMojoExecutes();

thenBuildxRun(null, null, true, "--provenance=mode=max");
thenBuildxRun(null, null, true, Collections.singletonList("--provenance=mode=max"));
}

@Test
Expand All @@ -195,7 +196,7 @@ void buildUsingBuildxWithNoProvenance() throws IOException, MojoExecutionExcepti

whenMojoExecutes();

thenBuildxRun(null, null, true, "--provenance=false");
thenBuildxRun(null, null, true, Collections.singletonList("--provenance=false"));
}

@Test
Expand All @@ -208,7 +209,26 @@ void buildUsingBuildxWithIncorrectProvenanceMode() throws IOException, MojoExecu

whenMojoExecutes();

thenBuildxRun(null, null, true, null);
thenBuildxRun(null, null, true, Collections.emptyList());
}

@Test
void buildUsingBuildxWithSecretEnvsFiles() throws IOException, MojoExecutionException {
givenBuildXService();

givenMavenProject(buildMojo);
givenResolvedImages(buildMojo, Collections.singletonList(singleBuildXImageWithSecret(
Collections.singletonMap("githubToken", "GITHUB_TOKEN"), Collections.singletonMap("privateRepo", "../private.repo"))));
givenPackaging("jar");

whenMojoExecutes();

List<String> secrets = new ArrayList<>();
secrets.add("--secret");
secrets.add("id=githubToken,env=GITHUB_TOKEN");
secrets.add("--secret");
secrets.add("id=privateRepo,src=../private.repo");
thenBuildxRun(null, null, true, secrets);
}

@Test
Expand Down Expand Up @@ -269,7 +289,7 @@ void buildWithTagByBuildx(boolean skipTag) throws IOException, MojoExecutionExce
List<String> fullTags = skipTag ? Collections.emptyList() : tags.stream()
.map(tag -> new ImageName(imageConfiguration.getName(), tag).getFullName())
.collect(Collectors.toList());
thenBuildxRun(null, null, true, null, fullTags);
thenBuildxRun(null, null, true, Collections.emptyList(), fullTags);
}

@ParameterizedTest
Expand Down Expand Up @@ -347,12 +367,13 @@ private void verifyBuild(int wantedNumberOfInvocations) throws DockerAccessExcep
}

private void thenBuildxRun(String relativeConfigFile, String contextDir, boolean nativePlatformIncluded,
String attestation) throws MojoExecutionException {
thenBuildxRun(relativeConfigFile, contextDir, nativePlatformIncluded, attestation, Collections.emptyList());
List<String> additionalParameters) throws MojoExecutionException {
thenBuildxRun(relativeConfigFile, contextDir, nativePlatformIncluded, additionalParameters,
Collections.emptyList());
}

private void thenBuildxRun(String relativeConfigFile, String contextDir,
boolean nativePlatformIncluded, String attestation, List<String> tags)
private void thenBuildxRun(String relativeConfigFile, String contextDir, boolean nativePlatformIncluded,
List<String> additionalParameters, List<String> tags)
throws MojoExecutionException {
Path buildPath = projectBaseDirectory.toPath().resolve("target/docker/example/latest");
String config = getOsDependentBuild(buildPath, "docker");
Expand Down Expand Up @@ -380,9 +401,7 @@ private void thenBuildxRun(String relativeConfigFile, String contextDir,
buildXLine.add("--build-arg");
buildXLine.add("foo=bar");

if (attestation != null) {
buildXLine.add(attestation);
}
buildXLine.addAll(additionalParameters);

if (contextDir == null) {
buildXLine.add(getOsDependentBuild(buildPath, "build"));
Expand Down Expand Up @@ -446,6 +465,12 @@ private ImageConfiguration singleBuildXImageWithAttestations(Boolean sbom, Strin
.build(), null);
}

private ImageConfiguration singleBuildXImageWithSecret(Map<String, String> envs, Map<String, String> files) {
return singleImageConfiguration(getBuildXPlatforms(TWO_BUILDX_PLATFORMS).secret(
new SecretConfiguration.Builder().envs(envs).files(files).build())
.build(), null);
}

protected ImageConfiguration singleImageWithAuthRegistry(String dockerFile) {
BuildImageConfiguration buildImageConfiguration = new BuildImageConfiguration.Builder()
.dockerFile(dockerFile)
Expand Down

0 comments on commit 76975c6

Please sign in to comment.