github.com/rish1988/moby@v25.0.2+incompatible/integration/capabilities/capabilities_linux_test.go (about)

     1  package capabilities
     2  
     3  import (
     4  	"bytes"
     5  	"io"
     6  	"strings"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/docker/docker/api/types"
    11  	containertypes "github.com/docker/docker/api/types/container"
    12  	"github.com/docker/docker/integration/internal/container"
    13  	"github.com/docker/docker/pkg/stdcopy"
    14  	"github.com/docker/docker/testutil"
    15  	"github.com/docker/docker/testutil/fakecontext"
    16  
    17  	"gotest.tools/v3/assert"
    18  	"gotest.tools/v3/poll"
    19  )
    20  
    21  func TestNoNewPrivileges(t *testing.T) {
    22  	ctx := setupTest(t)
    23  
    24  	withFileCapability := `
    25  		FROM debian:bullseye-slim
    26  		RUN apt-get update && apt-get install -y libcap2-bin --no-install-recommends
    27  		RUN setcap CAP_DAC_OVERRIDE=+eip /bin/cat
    28  		RUN echo "hello" > /txt && chown 0:0 /txt && chmod 700 /txt
    29  		RUN useradd -u 1500 test
    30  	`
    31  	imageTag := "captest"
    32  
    33  	source := fakecontext.New(t, "", fakecontext.WithDockerfile(withFileCapability))
    34  	defer source.Close()
    35  
    36  	client := testEnv.APIClient()
    37  
    38  	// Build image
    39  	resp, err := client.ImageBuild(ctx,
    40  		source.AsTarReader(t),
    41  		types.ImageBuildOptions{
    42  			Tags: []string{imageTag},
    43  		})
    44  	assert.NilError(t, err)
    45  	_, err = io.Copy(io.Discard, resp.Body)
    46  	assert.NilError(t, err)
    47  	resp.Body.Close()
    48  
    49  	testCases := []struct {
    50  		doc            string
    51  		opts           []func(*container.TestContainerConfig)
    52  		stdOut, stdErr string
    53  	}{
    54  		{
    55  			doc: "CapabilityRequested=true",
    56  			opts: []func(*container.TestContainerConfig){
    57  				container.WithUser("test"),
    58  				container.WithCapability("CAP_DAC_OVERRIDE"),
    59  			},
    60  			stdOut: "hello",
    61  		},
    62  		{
    63  			doc: "CapabilityRequested=false",
    64  			opts: []func(*container.TestContainerConfig){
    65  				container.WithUser("test"),
    66  				container.WithDropCapability("CAP_DAC_OVERRIDE"),
    67  			},
    68  			stdErr: "exec /bin/cat: operation not permitted",
    69  		},
    70  	}
    71  
    72  	for _, tc := range testCases {
    73  		tc := tc
    74  		t.Run(tc.doc, func(t *testing.T) {
    75  			ctx := testutil.StartSpan(ctx, t)
    76  
    77  			// Run the container with the image
    78  			opts := append(tc.opts,
    79  				container.WithImage(imageTag),
    80  				container.WithCmd("/bin/cat", "/txt"),
    81  				container.WithSecurityOpt("no-new-privileges=true"),
    82  			)
    83  			cid := container.Run(ctx, t, client, opts...)
    84  			poll.WaitOn(t, container.IsInState(ctx, client, cid, "exited"), poll.WithDelay(100*time.Millisecond))
    85  
    86  			// Assert on outputs
    87  			logReader, err := client.ContainerLogs(ctx, cid, containertypes.LogsOptions{
    88  				ShowStdout: true,
    89  				ShowStderr: true,
    90  			})
    91  			assert.NilError(t, err)
    92  			defer logReader.Close()
    93  
    94  			var actualStdout, actualStderr bytes.Buffer
    95  			_, err = stdcopy.StdCopy(&actualStdout, &actualStderr, logReader)
    96  			assert.NilError(t, err)
    97  
    98  			stdOut := strings.TrimSpace(actualStdout.String())
    99  			stdErr := strings.TrimSpace(actualStderr.String())
   100  			if stdOut != tc.stdOut {
   101  				t.Fatalf("test produced invalid output: %q, expected %q. Stderr:%q", stdOut, tc.stdOut, stdErr)
   102  			}
   103  			if stdErr != tc.stdErr {
   104  				t.Fatalf("test produced invalid error: %q, expected %q. Stdout:%q", stdErr, tc.stdErr, stdOut)
   105  			}
   106  		})
   107  	}
   108  }