github.com/rish1988/moby@v25.0.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  	"io"
     7  	"os"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/docker/docker/api/types"
    12  	containertypes "github.com/docker/docker/api/types/container"
    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"
    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  	ctx := testutil.StartSpan(baseContext, t)
    35  
    36  	const imageTag = "capabilities:1.0"
    37  
    38  	tmp, err := os.MkdirTemp("", "integration-")
    39  	assert.NilError(t, err)
    40  	defer os.RemoveAll(tmp)
    41  
    42  	dUserRemap := daemon.New(t)
    43  	dUserRemap.Start(t, "--userns-remap", "default")
    44  	clientUserRemap := dUserRemap.NewClientT(t)
    45  	defer clientUserRemap.Close()
    46  
    47  	err = load.FrozenImagesLinux(ctx, clientUserRemap, "debian:bookworm-slim")
    48  	assert.NilError(t, err)
    49  
    50  	dUserRemapRunning := true
    51  	defer func() {
    52  		if dUserRemapRunning {
    53  			dUserRemap.Stop(t)
    54  			dUserRemap.Cleanup(t)
    55  		}
    56  	}()
    57  
    58  	dockerfile := `
    59  		FROM debian:bookworm-slim
    60  		RUN apt-get update && apt-get install -y libcap2-bin --no-install-recommends
    61  		RUN setcap CAP_NET_BIND_SERVICE=+eip /bin/sleep
    62  	`
    63  
    64  	source := fakecontext.New(t, "", fakecontext.WithDockerfile(dockerfile))
    65  	defer source.Close()
    66  
    67  	resp, err := clientUserRemap.ImageBuild(ctx,
    68  		source.AsTarReader(t),
    69  		types.ImageBuildOptions{
    70  			Tags: []string{imageTag},
    71  		})
    72  	assert.NilError(t, err)
    73  	defer resp.Body.Close()
    74  
    75  	buf := bytes.NewBuffer(nil)
    76  	err = jsonmessage.DisplayJSONMessagesStream(resp.Body, buf, 0, false, nil)
    77  	assert.NilError(t, err)
    78  
    79  	reader, err := clientUserRemap.ImageSave(ctx, []string{imageTag})
    80  	assert.NilError(t, err, "failed to download capabilities image")
    81  	defer reader.Close()
    82  
    83  	tar, err := os.Create(tmp + "/image.tar")
    84  	assert.NilError(t, err, "failed to create image tar file")
    85  	defer tar.Close()
    86  
    87  	_, err = io.Copy(tar, reader)
    88  	assert.NilError(t, err, "failed to write image tar file")
    89  
    90  	dUserRemap.Stop(t)
    91  	dUserRemap.Cleanup(t)
    92  	dUserRemapRunning = false
    93  
    94  	dNoUserRemap := daemon.New(t)
    95  	dNoUserRemap.Start(t)
    96  	defer func() {
    97  		dNoUserRemap.Stop(t)
    98  		dNoUserRemap.Cleanup(t)
    99  	}()
   100  
   101  	clientNoUserRemap := dNoUserRemap.NewClientT(t)
   102  	defer clientNoUserRemap.Close()
   103  
   104  	tarFile, err := os.Open(tmp + "/image.tar")
   105  	assert.NilError(t, err, "failed to open image tar file")
   106  	defer tarFile.Close()
   107  
   108  	tarReader := bufio.NewReader(tarFile)
   109  	loadResp, err := clientNoUserRemap.ImageLoad(ctx, tarReader, false)
   110  	assert.NilError(t, err, "failed to load image tar file")
   111  	defer loadResp.Body.Close()
   112  	buf = bytes.NewBuffer(nil)
   113  	err = jsonmessage.DisplayJSONMessagesStream(loadResp.Body, buf, 0, false, nil)
   114  	assert.NilError(t, err)
   115  
   116  	cid := container.Run(ctx, t, clientNoUserRemap,
   117  		container.WithImage(imageTag),
   118  		container.WithCmd("/sbin/getcap", "-n", "/bin/sleep"),
   119  	)
   120  	logReader, err := clientNoUserRemap.ContainerLogs(ctx, cid, containertypes.LogsOptions{
   121  		ShowStdout: true,
   122  	})
   123  	assert.NilError(t, err)
   124  	defer logReader.Close()
   125  
   126  	actualStdout := new(bytes.Buffer)
   127  	actualStderr := io.Discard
   128  	_, err = stdcopy.StdCopy(actualStdout, actualStderr, logReader)
   129  	assert.NilError(t, err)
   130  	if strings.TrimSpace(actualStdout.String()) != "/bin/sleep cap_net_bind_service=eip" {
   131  		t.Fatalf("run produced invalid output: %q, expected %q", actualStdout.String(), "/bin/sleep cap_net_bind_service=eip")
   132  	}
   133  }