Skip to content

Commit

Permalink
Disable SELinux label security policy when building images
Browse files Browse the repository at this point in the history
When using the Gradle `bootBuildImage` task or Maven
`spring-boot:build-image` goal on a Linux distribution with SELinux
enabled, binding the Docker socket in the builder container might
fail. This commit disables the `label` security policy in the builder
container to prevent this type of failure.

Fixes gh-32000
  • Loading branch information
scottfrederick committed Aug 19, 2022
1 parent 238493a commit c16094e
Show file tree
Hide file tree
Showing 14 changed files with 78 additions and 5 deletions.
Expand Up @@ -20,6 +20,8 @@
import java.io.IOException;
import java.util.function.Consumer;

import com.sun.jna.Platform;

import org.springframework.boot.buildpack.platform.docker.DockerApi;
import org.springframework.boot.buildpack.platform.docker.LogUpdateEvent;
import org.springframework.boot.buildpack.platform.docker.configuration.ResolvedDockerHost;
Expand Down Expand Up @@ -201,6 +203,9 @@ private void configureDaemonAccess(Phase phase) {
else {
phase.withBinding(Binding.from(DOMAIN_SOCKET_PATH, DOMAIN_SOCKET_PATH));
}
if (!Platform.isWindows()) {
phase.withSecurityOption("label=disable");
}
}

private boolean isVerboseLogging() {
Expand Down
Expand Up @@ -47,6 +47,8 @@ class Phase {

private final Map<String, String> env = new LinkedHashMap<>();

private final List<String> securityOptions = new ArrayList<>();

private String networkMode;

/**
Expand Down Expand Up @@ -110,6 +112,14 @@ void withNetworkMode(String networkMode) {
this.networkMode = networkMode;
}

/**
* Update this phase with a security option.
* @param option the security option
*/
void withSecurityOption(String option) {
this.securityOptions.add(option);
}

/**
* Return the name of the phase.
* @return the phase name
Expand Down Expand Up @@ -138,6 +148,7 @@ void apply(ContainerConfig.Update update) {
if (this.networkMode != null) {
update.withNetworkMode(this.networkMode);
}
this.securityOptions.forEach(update::withSecurityOption);
}

}
Expand Up @@ -48,7 +48,8 @@ public class ContainerConfig {
private final String json;

ContainerConfig(String user, ImageReference image, String command, List<String> args, Map<String, String> labels,
List<Binding> bindings, Map<String, String> env, String networkMode) throws IOException {
List<Binding> bindings, Map<String, String> env, String networkMode, List<String> securityOptions)
throws IOException {
Assert.notNull(image, "Image must not be null");
Assert.hasText(command, "Command must not be empty");
ObjectMapper objectMapper = SharedObjectMapper.get();
Expand All @@ -70,6 +71,10 @@ public class ContainerConfig {
}
ArrayNode bindsNode = hostConfigNode.putArray("Binds");
bindings.forEach((binding) -> bindsNode.add(binding.toString()));
if (securityOptions != null && !securityOptions.isEmpty()) {
ArrayNode securityOptsNode = hostConfigNode.putArray("SecurityOpt");
securityOptions.forEach(securityOptsNode::add);
}
this.json = objectMapper.writeValueAsString(node);
}

Expand Down Expand Up @@ -120,6 +125,8 @@ public static class Update {

private String networkMode;

private final List<String> securityOptions = new ArrayList<>();

Update(ImageReference image) {
this.image = image;
}
Expand All @@ -128,7 +135,7 @@ private ContainerConfig run(Consumer<Update> update) {
update.accept(this);
try {
return new ContainerConfig(this.user, this.image, this.command, this.args, this.labels, this.bindings,
this.env, this.networkMode);
this.env, this.networkMode, this.securityOptions);
}
catch (IOException ex) {
throw new IllegalStateException(ex);
Expand Down Expand Up @@ -197,6 +204,14 @@ public void withNetworkMode(String networkMode) {
this.networkMode = networkMode;
}

/**
* Update the container config with a security option.
* @param option the security option
*/
public void withSecurityOption(String option) {
this.securityOptions.add(option);
}

}

}
Expand Up @@ -143,4 +143,18 @@ void applyWhenWithNetworkModeUpdatesConfigurationWithNetworkMode() {
then(update).shouldHaveNoMoreInteractions();
}

@Test
void applyWhenWithSecurityOptionsUpdatesConfigurationWithSecurityOptions() {
Phase phase = new Phase("test", true);
phase.withSecurityOption("option1=value1");
phase.withSecurityOption("option2=value2");
Update update = mock(Update.class);
phase.apply(update);
then(update).should().withCommand("/cnb/lifecycle/test");
then(update).should().withLabel("author", "spring-boot");
then(update).should().withSecurityOption("option1=value1");
then(update).should().withSecurityOption("option2=value2");
then(update).shouldHaveNoMoreInteractions();
}

}
Expand Up @@ -61,12 +61,13 @@ void writeToWritesJson() throws Exception {
update.withEnv("name1", "value1");
update.withEnv("name2", "value2");
update.withNetworkMode("test");
update.withSecurityOption("option=value");
});
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
containerConfig.writeTo(outputStream);
String actualJson = new String(outputStream.toByteArray(), StandardCharsets.UTF_8);
String expectedJson = StreamUtils.copyToString(getContent("container-config.json"), StandardCharsets.UTF_8);
JSONAssert.assertEquals(expectedJson, actualJson, false);
JSONAssert.assertEquals(expectedJson, actualJson, true);
}

}
Expand Up @@ -33,6 +33,9 @@
"pack-cache-b35197ac41ea.launch:/launch-cache",
"/host/src/path:/container/dest/path:ro",
"volume-name:/container/volume/path:rw"
],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -31,6 +31,9 @@
"pack-app-aaaaaaaaaa:/workspace",
"build-volume:/cache",
"launch-volume:/launch-cache"
],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -32,6 +32,9 @@
"pack-app-aaaaaaaaaa:/workspace",
"pack-cache-b35197ac41ea.build:/cache",
"pack-cache-b35197ac41ea.launch:/launch-cache"
],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -31,6 +31,9 @@
"pack-app-aaaaaaaaaa:/workspace",
"pack-cache-b35197ac41ea.build:/cache",
"pack-cache-b35197ac41ea.launch:/launch-cache"
],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -31,6 +31,9 @@
"pack-app-aaaaaaaaaa:/workspace",
"pack-cache-b35197ac41ea.build:/cache",
"pack-cache-b35197ac41ea.launch:/launch-cache"
],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -32,6 +32,9 @@
"pack-app-aaaaaaaaaa:/workspace",
"pack-cache-b35197ac41ea.build:/cache",
"pack-cache-b35197ac41ea.launch:/launch-cache"
],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -7,6 +7,9 @@
"author" : "spring-boot"
},
"HostConfig" : {
"Binds" : [ "/var/run/docker.sock:/var/run/docker.sock", "pack-layers-aaaaaaaaaa:/layers", "pack-app-aaaaaaaaaa:/workspace", "pack-cache-b35197ac41ea.build:/cache", "pack-cache-b35197ac41ea.launch:/launch-cache" ]
"Binds" : [ "/var/run/docker.sock:/var/run/docker.sock", "pack-layers-aaaaaaaaaa:/layers", "pack-app-aaaaaaaaaa:/workspace", "pack-cache-b35197ac41ea.build:/cache", "pack-cache-b35197ac41ea.launch:/launch-cache" ],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -31,6 +31,9 @@
"pack-app-aaaaaaaaaa:/workspace",
"pack-cache-b35197ac41ea.build:/cache",
"pack-cache-b35197ac41ea.launch:/launch-cache"
],
"SecurityOpt" : [
"label=disable"
]
}
}
Expand Up @@ -17,6 +17,9 @@
"Binds": [
"bind-source:bind-dest"
],
"NetworkMode": "test"
"NetworkMode": "test",
"SecurityOpt": [
"option=value"
]
}
}

0 comments on commit c16094e

Please sign in to comment.