builder: prevent Dockerfile to leave build context

Signed-off-by: Tibor Vass <teabee89@gmail.com>
This commit is contained in:
Tibor Vass
2015-02-02 23:40:24 -08:00
committed by Arnaud Porterie
parent 198ff76de5
commit 73d5baf585
4 changed files with 132 additions and 35 deletions
+39 -4
View File
@@ -307,13 +307,14 @@ func TestBuildApiDockerfilePath(t *testing.T) {
tw := tar.NewWriter(buffer)
defer tw.Close()
dockerfile := []byte("FROM busybox")
if err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Size: 11,
Size: int64(len(dockerfile)),
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
}
if _, err := tw.Write([]byte("FROM ubuntu")); err != nil {
if _, err := tw.Write(dockerfile); err != nil {
t.Fatalf("failed to write tar file content: %v", err)
}
if err := tw.Close(); err != nil {
@@ -322,12 +323,46 @@ func TestBuildApiDockerfilePath(t *testing.T) {
out, err := sockRequestRaw("POST", "/build?dockerfile=../Dockerfile", buffer, "application/x-tar")
if err == nil {
t.Fatalf("Build was supposed to fail")
t.Fatalf("Build was supposed to fail: %s", out)
}
if !strings.Contains(string(out), "must be within the build context") {
t.Fatalf("Didn't complain about leaving build context")
t.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile path")
}
func TestBuildApiDockerfileSymlink(t *testing.T) {
// Test to make sure we stop people from trying to leave the
// build context when specifying a symlink as the path to the dockerfile
buffer := new(bytes.Buffer)
tw := tar.NewWriter(buffer)
defer tw.Close()
if err := tw.WriteHeader(&tar.Header{
Name: "Dockerfile",
Typeflag: tar.TypeSymlink,
Linkname: "/etc/passwd",
}); err != nil {
t.Fatalf("failed to write tar file header: %v", err)
}
if err := tw.Close(); err != nil {
t.Fatalf("failed to close tar archive: %v", err)
}
out, err := sockRequestRaw("POST", "/build", buffer, "application/x-tar")
if err == nil {
t.Fatalf("Build was supposed to fail: %s", out)
}
// The reason the error is "Cannot locate specified Dockerfile" is because
// in the builder, the symlink is resolved within the context, therefore
// Dockerfile -> /etc/passwd becomes etc/passwd from the context which is
// a nonexistent file.
if !strings.Contains(string(out), "Cannot locate specified Dockerfile: Dockerfile") {
t.Fatalf("Didn't complain about leaving build context: %s", out)
}
logDone("container REST API - check build w/bad Dockerfile symlink path")
}
+64
View File
@@ -4630,3 +4630,67 @@ func TestBuildFromOfficialNames(t *testing.T) {
}
logDone("build - from official names")
}
func TestBuildDockerfileOutsideContext(t *testing.T) {
name := "testbuilddockerfileoutsidecontext"
tmpdir, err := ioutil.TempDir("", name)
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
ctx := filepath.Join(tmpdir, "context")
if err := os.MkdirAll(ctx, 0755); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(ctx, "Dockerfile"), []byte("FROM busybox"), 0644); err != nil {
t.Fatal(err)
}
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
defer os.Chdir(wd)
if err := os.Chdir(ctx); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filepath.Join(tmpdir, "outsideDockerfile"), []byte("FROM busbox"), 0644); err != nil {
t.Fatal(err)
}
if err := os.Symlink("../outsideDockerfile", filepath.Join(ctx, "dockerfile1")); err != nil {
t.Fatal(err)
}
if err := os.Symlink(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile2")); err != nil {
t.Fatal(err)
}
if err := os.Link("../outsideDockerfile", filepath.Join(ctx, "dockerfile3")); err != nil {
t.Fatal(err)
}
if err := os.Link(filepath.Join(tmpdir, "outsideDockerfile"), filepath.Join(ctx, "dockerfile4")); err != nil {
t.Fatal(err)
}
for _, dockerfilePath := range []string{
"../outsideDockerfile",
filepath.Join(ctx, "dockerfile1"),
filepath.Join(ctx, "dockerfile2"),
filepath.Join(ctx, "dockerfile3"),
filepath.Join(ctx, "dockerfile4"),
} {
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", dockerfilePath, "."))
if err == nil {
t.Fatalf("Expected error with %s. Out: %s", dockerfilePath, out)
}
deleteImages(name)
}
os.Chdir(tmpdir)
// Path to Dockerfile should be resolved relative to working directory, not relative to context.
// There is a Dockerfile in the context, but since there is no Dockerfile in the current directory, the following should fail
out, _, err := runCommandWithOutput(exec.Command(dockerBinary, "build", "-t", name, "--no-cache", "-f", "Dockerfile", ctx))
if err == nil {
t.Fatalf("Expected error. Out: %s", out)
}
deleteImages(name)
logDone("build - Dockerfile outside context")
}