Add warning if sensitive container paths are bound
Closes gh-41643
This commit is contained in:
@@ -32,6 +32,7 @@ import org.springframework.boot.buildpack.platform.docker.DockerApi.VolumeApi;
|
||||
import org.springframework.boot.buildpack.platform.docker.TotalProgressPullListener;
|
||||
import org.springframework.boot.buildpack.platform.docker.configuration.DockerConfiguration;
|
||||
import org.springframework.boot.buildpack.platform.docker.transport.DockerEngineException;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.Binding;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.ContainerReference;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.ContainerStatus;
|
||||
import org.springframework.boot.buildpack.platform.docker.type.Image;
|
||||
@@ -521,6 +522,26 @@ class BuilderTests {
|
||||
.withMessageContaining("not found in builder");
|
||||
}
|
||||
|
||||
@Test
|
||||
void logsWarningIfBindingWithSensitiveTargetIsDetected() throws IOException {
|
||||
TestPrintStream out = new TestPrintStream();
|
||||
DockerApi docker = mockDockerApi();
|
||||
Image builderImage = loadImage("image.json");
|
||||
Image runImage = loadImage("run-image.json");
|
||||
given(docker.image()
|
||||
.pull(eq(ImageReference.of(BuildRequest.DEFAULT_BUILDER_IMAGE_REF)), isNull(), any(), isNull()))
|
||||
.willAnswer(withPulledImage(builderImage));
|
||||
given(docker.image()
|
||||
.pull(eq(ImageReference.of("docker.io/cloudfoundry/run:base-cnb")), eq(ImagePlatform.from(builderImage)),
|
||||
any(), isNull()))
|
||||
.willAnswer(withPulledImage(runImage));
|
||||
Builder builder = new Builder(BuildLog.to(out), docker, null);
|
||||
BuildRequest request = getTestRequest().withBindings(Binding.from("/host", "/cnb"));
|
||||
builder.build(request);
|
||||
assertThat(out.toString()).contains(
|
||||
"Warning: Binding '/host:/cnb' uses a container path which is used by buildpacks while building. Binding to it can cause problems!");
|
||||
}
|
||||
|
||||
private DockerApi mockDockerApi() throws IOException {
|
||||
return mockDockerApi(null);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -17,14 +17,18 @@
|
||||
package org.springframework.boot.buildpack.platform.docker.type;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.CsvSource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* Tests for {@link Binding}.
|
||||
*
|
||||
* @author Scott Frederick
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class BindingTests {
|
||||
|
||||
@@ -70,4 +74,51 @@ class BindingTests {
|
||||
.withMessageContaining("SourceVolume must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnContainerDestinationPath() {
|
||||
Binding binding = Binding.from("/host", "/container");
|
||||
assertThat(binding.getContainerDestinationPath()).isEqualTo("/container");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnContainerDestinationPathWithOptions() {
|
||||
Binding binding = Binding.of("/host:/container:ro");
|
||||
assertThat(binding.getContainerDestinationPath()).isEqualTo("/container");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnContainerDestinationPathOnWindows() {
|
||||
Binding binding = Binding.from("C:\\host", "C:\\container");
|
||||
assertThat(binding.getContainerDestinationPath()).isEqualTo("C:\\container");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReturnContainerDestinationPathOnWindowsWithOptions() {
|
||||
Binding binding = Binding.of("C:\\host:C:\\container:ro");
|
||||
assertThat(binding.getContainerDestinationPath()).isEqualTo("C:\\container");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailIfBindingIsMalformed() {
|
||||
Binding binding = Binding.of("some-invalid-binding");
|
||||
assertThatIllegalStateException().isThrownBy(binding::getContainerDestinationPath)
|
||||
.withMessage("Expected 2 or more parts, but found 1");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@CsvSource(textBlock = """
|
||||
/cnb, true
|
||||
/layers, true
|
||||
/workspace, true
|
||||
/something, false
|
||||
c:\\cnb, true
|
||||
c:\\layers, true
|
||||
c:\\workspace, true
|
||||
c:\\something, false
|
||||
""")
|
||||
void shouldDetectSensitiveContainerPaths(String containerPath, boolean sensitive) {
|
||||
Binding binding = Binding.from("/host", containerPath);
|
||||
assertThat(binding.usesSensitiveContainerPath()).isEqualTo(sensitive);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user