integration: secmode switch support and security testcase

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
Signed-off-by: Kunal Kushwaha <kunal.kushwaha@gmail.com>
docker-19.03
Tonis Tiigi 2019-02-01 16:20:18 -08:00 committed by Kunal Kushwaha
parent a2bbb5ff39
commit 01a8de7d74
5 changed files with 144 additions and 23 deletions

View File

@ -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{}

View File

@ -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
}

View File

@ -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
}

View File

@ -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

2
vendor/modules.txt vendored
View File

@ -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