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
parent
a2bbb5ff39
commit
01a8de7d74
|
@ -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{}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue