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