diff --git a/client/client_test.go b/client/client_test.go index c8d6dbc3..d11a8408 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -34,6 +34,7 @@ import ( "github.com/moby/buildkit/session/secrets/secretsprovider" "github.com/moby/buildkit/session/sshforward/sshprovider" "github.com/moby/buildkit/util/contentutil" + "github.com/moby/buildkit/util/entitlements" "github.com/moby/buildkit/util/testutil" "github.com/moby/buildkit/util/testutil/httpserver" "github.com/moby/buildkit/util/testutil/integration" @@ -51,6 +52,8 @@ type nopWriteCloser struct { func (nopWriteCloser) Close() error { return nil } func TestClientIntegration(t *testing.T) { + mirrors := integration.WithMirroredImages(integration.OfficialImages("busybox:latest", "alpine:latest")) + integration.Run(t, []integration.Test{ testRelativeWorkDir, testFileOpMkdirMkfile, @@ -88,9 +91,18 @@ func TestClientIntegration(t *testing.T) { testHostnameLookup, testPushByDigest, testBasicInlineCacheImportExport, + testExportBusyboxLocal, + }, mirrors) + + integration.Run(t, []integration.Test{ testSecurityMode, + testSecurityModeErrors, }, - integration.WithMirroredImages(integration.OfficialImages("busybox:latest", "alpine:latest")), + mirrors, + integration.WithMatrix("secmode", map[string]interface{}{ + "sandbox": securitySandbox, + "insecure": securityInsecure, + }), ) } @@ -420,32 +432,81 @@ func testPushByDigest(t *testing.T, sb integration.Sandbox) { } func testSecurityMode(t *testing.T, sb integration.Sandbox) { + var command string + mode := llb.SecurityModeSandbox + var allowedEntitlements []entitlements.Entitlement + secMode := sb.Value("secmode") + if secMode == securitySandbox { + /* + $ capsh --decode=00000000a80425fb + 0x00000000a80425fb=cap_chown,cap_dac_override,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap, + cap_net_bind_service,cap_net_raw,cap_sys_chroot,cap_mknod,cap_audit_write,cap_setfcap + */ + command = `sh -c 'cat /proc/self/status | grep CapEff | grep "00000000a80425fb"'` + allowedEntitlements = []entitlements.Entitlement{} + } else { + /* + $ capsh --decode=0000003fffffffff + 0x0000003fffffffff=cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid, + cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw, + cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin, + cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write, + cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,cap_wake_alarm,cap_block_suspend,cap_audit_read + */ + command = `sh -c 'cat /proc/self/status | grep CapEff | grep "0000003fffffffff"'` + mode = llb.SecurityModeInsecure + allowedEntitlements = []entitlements.Entitlement{entitlements.EntitlementSecurityInsecure} + } c, err := New(context.TODO(), sb.Address()) require.NoError(t, err) defer c.Close() st := llb.Image("busybox:latest"). - Run(llb.Shlex(`sh -c 'echo confined'`)) + Run(llb.Shlex(command), + llb.Security(mode)) def, err := st.Marshal() require.NoError(t, err) - _, err = c.Solve(context.TODO(), def, SolveOpt{}, nil) - require.NoError(t, err) - - st2 := llb.Image("busybox:latest"). - Run(llb.Shlex(`sh -c 'echo unconfined'`), llb.Security(llb.SecurityModeUnconfined)) - - def, err = st2.Marshal() - require.NoError(t, err) - _, err = c.Solve(context.TODO(), def, SolveOpt{ - // Currently disabled globally by default - //AllowedEntitlements: []entitlements.Entitlement{entitlements.EntitlementSecurityUnconfined}, + AllowedEntitlements: allowedEntitlements, }, nil) - require.Error(t, err) - require.Contains(t, err.Error(), "security.unconfined is not allowed") + + require.NoError(t, err) +} + +func testSecurityModeErrors(t *testing.T, sb integration.Sandbox) { + + c, err := New(context.TODO(), sb.Address()) + require.NoError(t, err) + defer c.Close() + secMode := sb.Value("secmode") + if secMode == securitySandbox { + + st := llb.Image("busybox:latest"). + Run(llb.Shlex(`sh -c 'echo sandbox'`)) + + def, err := st.Marshal() + require.NoError(t, err) + + _, err = c.Solve(context.TODO(), def, SolveOpt{ + AllowedEntitlements: []entitlements.Entitlement{entitlements.EntitlementSecurityInsecure}, + }, nil) + require.Error(t, err) + require.Contains(t, err.Error(), "security.insecure is not allowed") + } + if secMode == securityInsecure { + st := llb.Image("busybox:latest"). + Run(llb.Shlex(`sh -c 'echo insecure'`), llb.Security(llb.SecurityModeInsecure)) + + def, err := st.Marshal() + require.NoError(t, err) + + _, err = c.Solve(context.TODO(), def, SolveOpt{}, nil) + require.Error(t, err) + require.Contains(t, err.Error(), "security.insecure is not allowed") + } } func testFrontendImageNaming(t *testing.T, sb integration.Sandbox) { @@ -2363,3 +2424,18 @@ func (s *server) run(a agent.Agent) error { go agent.ServeAgent(a, c) } } + +type secModeSandbox struct{} + +func (*secModeSandbox) UpdateConfigFile(in string) string { + return in +} + +type secModeInsecure struct{} + +func (*secModeInsecure) UpdateConfigFile(in string) string { + return in + "\n\ninsecure-entitlements = [\"security.insecure\"]\n" +} + +var securitySandbox integration.ConfigUpdater = &secModeSandbox{} +var securityInsecure integration.ConfigUpdater = &secModeInsecure{} diff --git a/util/testutil/integration/containerd.go b/util/testutil/integration/containerd.go index 7751830c..511aa18e 100644 --- a/util/testutil/integration/containerd.go +++ b/util/testutil/integration/containerd.go @@ -129,8 +129,20 @@ disabled_plugins = ["cri"] "--containerd-worker-labels=org.mobyproject.buildkit.worker.sandbox=true", // Include use of --containerd-worker-labels to trigger https://github.com/moby/buildkit/pull/603 } + var upt []ConfigUpdater + + for _, v := range conf.mv.values { + if u, ok := v.value.(ConfigUpdater); ok { + upt = append(upt, u) + } + } + if conf.mirror != "" { - dir, err := configWithMirror(conf.mirror) + upt = append(upt, withMirrorConfig(conf.mirror)) + } + + if len(upt) > 0 { + dir, err := writeConfig(upt) if err != nil { return nil, nil, err } diff --git a/util/testutil/integration/oci.go b/util/testutil/integration/oci.go index c06ff053..2921fdfa 100644 --- a/util/testutil/integration/oci.go +++ b/util/testutil/integration/oci.go @@ -64,8 +64,20 @@ func (s *oci) New(opt ...SandboxOpt) (Sandbox, func() error, error) { deferF := &multiCloser{} + var upt []ConfigUpdater + + for _, v := range c.mv.values { + if u, ok := v.value.(ConfigUpdater); ok { + upt = append(upt, u) + } + } + if c.mirror != "" { - dir, err := configWithMirror(c.mirror) + upt = append(upt, withMirrorConfig(c.mirror)) + } + + if len(upt) > 0 { + dir, err := writeConfig(upt) if err != nil { return nil, nil, err } diff --git a/util/testutil/integration/run.go b/util/testutil/integration/run.go index a3223a2c..c1dd8ec3 100644 --- a/util/testutil/integration/run.go +++ b/util/testutil/integration/run.go @@ -58,6 +58,10 @@ func withMatrixValues(mv matrixValue) SandboxOpt { } } +type ConfigUpdater interface { + UpdateConfigFile(string) string +} + type Test func(*testing.T, Sandbox) var defaultWorkers []Worker @@ -231,7 +235,21 @@ func OfficialImages(names ...string) map[string]string { return m } -func configWithMirror(mirror string) (string, error) { +func withMirrorConfig(mirror string) ConfigUpdater { + return mirrorConfig(mirror) +} + +type mirrorConfig string + +func (mc mirrorConfig) UpdateConfigFile(in string) string { + return fmt.Sprintf(`%s + +[registry."docker.io"] +mirrors=["%s"] +`, in, mc) +} + +func writeConfig(updaters []ConfigUpdater) (string, error) { tmpdir, err := ioutil.TempDir("", "bktest_config") if err != nil { return "", err @@ -239,10 +257,13 @@ func configWithMirror(mirror string) (string, error) { if err := os.Chmod(tmpdir, 0711); err != nil { return "", err } - if err := ioutil.WriteFile(filepath.Join(tmpdir, "buildkitd.toml"), []byte(fmt.Sprintf(` -[registry."docker.io"] -mirrors=["%s"] -`, mirror)), 0644); err != nil { + + s := "" + for _, upt := range updaters { + s = upt.UpdateConfigFile(s) + } + + if err := ioutil.WriteFile(filepath.Join(tmpdir, "buildkitd.toml"), []byte(s), 0644); err != nil { return "", err } return tmpdir, nil diff --git a/vendor/modules.txt b/vendor/modules.txt index 6c11f25a..94a3631f 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -41,9 +41,9 @@ github.com/containerd/containerd/snapshots/native github.com/containerd/containerd/snapshots/overlay github.com/containerd/containerd/sys github.com/containerd/containerd/cio -github.com/containerd/containerd/contrib/seccomp github.com/containerd/containerd/oci github.com/containerd/containerd/containers +github.com/containerd/containerd/contrib/seccomp github.com/containerd/containerd/namespaces github.com/containerd/containerd/errdefs github.com/containerd/containerd/images/oci