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  }