github.com/jfrazelle/docker@v1.1.2-0.20210712172922-bf78e25fe508/integration/build/build_userns_linux_test.go (about) 1 package build // import "github.com/docker/docker/integration/build" 2 3 import ( 4 "bufio" 5 "bytes" 6 "context" 7 "io" 8 "io/ioutil" 9 "os" 10 "strings" 11 "testing" 12 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/integration/internal/container" 15 "github.com/docker/docker/pkg/jsonmessage" 16 "github.com/docker/docker/pkg/stdcopy" 17 "github.com/docker/docker/testutil/daemon" 18 "github.com/docker/docker/testutil/fakecontext" 19 "github.com/docker/docker/testutil/fixtures/load" 20 "gotest.tools/v3/assert" 21 "gotest.tools/v3/skip" 22 ) 23 24 // Implements a test for https://github.com/moby/moby/issues/41723 25 // Images built in a user-namespaced daemon should have capabilities serialised in 26 // VFS_CAP_REVISION_2 (no user-namespace root uid) format rather than V3 (that includes 27 // the root uid). 28 func TestBuildUserNamespaceValidateCapabilitiesAreV2(t *testing.T) { 29 skip.If(t, testEnv.DaemonInfo.OSType != "linux") 30 skip.If(t, testEnv.IsRemoteDaemon()) 31 skip.If(t, !testEnv.IsUserNamespaceInKernel()) 32 skip.If(t, testEnv.IsRootless()) 33 34 const imageTag = "capabilities:1.0" 35 36 tmp, err := ioutil.TempDir("", "integration-") 37 assert.NilError(t, err) 38 defer os.RemoveAll(tmp) 39 40 dUserRemap := daemon.New(t) 41 dUserRemap.Start(t, "--userns-remap", "default") 42 ctx := context.Background() 43 clientUserRemap := dUserRemap.NewClientT(t) 44 45 err = load.FrozenImagesLinux(clientUserRemap, "debian:bullseye") 46 assert.NilError(t, err) 47 48 dUserRemapRunning := true 49 defer func() { 50 if dUserRemapRunning { 51 dUserRemap.Stop(t) 52 } 53 }() 54 55 dockerfile := ` 56 FROM debian:bullseye 57 RUN setcap CAP_NET_BIND_SERVICE=+eip /bin/sleep 58 ` 59 60 source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile)) 61 defer source.Close() 62 63 resp, err := clientUserRemap.ImageBuild(ctx, 64 source.AsTarReader(t), 65 types.ImageBuildOptions{ 66 Tags: []string{imageTag}, 67 }) 68 assert.NilError(t, err) 69 defer resp.Body.Close() 70 71 buf := bytes.NewBuffer(nil) 72 err = jsonmessage.DisplayJSONMessagesStream(resp.Body, buf, 0, false, nil) 73 assert.NilError(t, err) 74 75 reader, err := clientUserRemap.ImageSave(ctx, []string{imageTag}) 76 assert.NilError(t, err, "failed to download capabilities image") 77 defer reader.Close() 78 79 tar, err := os.Create(tmp + "/image.tar") 80 assert.NilError(t, err, "failed to create image tar file") 81 defer tar.Close() 82 83 _, err = io.Copy(tar, reader) 84 assert.NilError(t, err, "failed to write image tar file") 85 86 dUserRemap.Stop(t) 87 dUserRemap.Cleanup(t) 88 dUserRemapRunning = false 89 90 dNoUserRemap := daemon.New(t) 91 dNoUserRemap.Start(t) 92 defer dNoUserRemap.Stop(t) 93 94 clientNoUserRemap := dNoUserRemap.NewClientT(t) 95 96 tarFile, err := os.Open(tmp + "/image.tar") 97 assert.NilError(t, err, "failed to open image tar file") 98 99 tarReader := bufio.NewReader(tarFile) 100 loadResp, err := clientNoUserRemap.ImageLoad(ctx, tarReader, false) 101 assert.NilError(t, err, "failed to load image tar file") 102 defer loadResp.Body.Close() 103 buf = bytes.NewBuffer(nil) 104 err = jsonmessage.DisplayJSONMessagesStream(loadResp.Body, buf, 0, false, nil) 105 assert.NilError(t, err) 106 107 cid := container.Run(ctx, t, clientNoUserRemap, 108 container.WithImage(imageTag), 109 container.WithCmd("/sbin/getcap", "-n", "/bin/sleep"), 110 ) 111 logReader, err := clientNoUserRemap.ContainerLogs(ctx, cid, types.ContainerLogsOptions{ 112 ShowStdout: true, 113 }) 114 assert.NilError(t, err) 115 116 actualStdout := new(bytes.Buffer) 117 actualStderr := ioutil.Discard 118 _, err = stdcopy.StdCopy(actualStdout, actualStderr, logReader) 119 assert.NilError(t, err) 120 if strings.TrimSpace(actualStdout.String()) != "/bin/sleep cap_net_bind_service=eip" { 121 t.Fatalf("run produced invalid output: %q, expected %q", actualStdout.String(), "/bin/sleep cap_net_bind_service=eip") 122 } 123 }