117 lines
3.6 KiB
Go
117 lines
3.6 KiB
Go
//go:build linux
|
|
|
|
package daemon
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
containertypes "github.com/moby/moby/api/types/container"
|
|
"github.com/moby/moby/v2/daemon/container"
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
|
"gotest.tools/v3/assert"
|
|
)
|
|
|
|
func TestExecSetPlatformOptPreservesUmaskWhenResolvingUser(t *testing.T) {
|
|
root := t.TempDir()
|
|
assert.NilError(t, os.MkdirAll(filepath.Join(root, "etc"), 0o755))
|
|
assert.NilError(t, os.WriteFile(filepath.Join(root, "etc/passwd"), []byte("test:x:1234:5678::/:/bin/sh\n"), 0o644))
|
|
assert.NilError(t, os.WriteFile(filepath.Join(root, "etc/group"), []byte("test:x:5678:\n"), 0o644))
|
|
|
|
c := &container.Container{
|
|
BaseFS: root,
|
|
SecurityOptions: container.SecurityOptions{
|
|
AppArmorProfile: unconfinedAppArmorProfile,
|
|
},
|
|
HostConfig: &containertypes.HostConfig{},
|
|
}
|
|
ec := &container.ExecConfig{Container: c, User: "1234:5678"}
|
|
umask := uint32(0o027)
|
|
p := &specs.Process{User: specs.User{Umask: &umask}}
|
|
cfg := &configStore{}
|
|
|
|
err := (&Daemon{}).execSetPlatformOpt(t.Context(), &cfg.Config, ec, p)
|
|
assert.NilError(t, err)
|
|
assert.Equal(t, p.User.UID, uint32(1234))
|
|
assert.Equal(t, p.User.GID, uint32(5678))
|
|
assert.Assert(t, p.User.Umask != nil)
|
|
assert.Equal(t, *p.User.Umask, umask)
|
|
}
|
|
|
|
func TestExecSetPlatformOptAppArmor(t *testing.T) {
|
|
appArmorEnabled := appArmorSupported()
|
|
|
|
tests := []struct {
|
|
doc string
|
|
privileged bool
|
|
appArmorProfile string
|
|
expectedProfile string
|
|
}{
|
|
{
|
|
doc: "default options",
|
|
expectedProfile: defaultAppArmorProfile,
|
|
},
|
|
{
|
|
doc: "custom profile",
|
|
appArmorProfile: "my-custom-profile",
|
|
expectedProfile: "my-custom-profile",
|
|
},
|
|
{
|
|
doc: "privileged container",
|
|
privileged: true,
|
|
expectedProfile: unconfinedAppArmorProfile,
|
|
},
|
|
{
|
|
doc: "privileged container, custom profile",
|
|
privileged: true,
|
|
appArmorProfile: "my-custom-profile",
|
|
expectedProfile: "my-custom-profile",
|
|
// FIXME: execSetPlatformOpts prefers custom profiles over "privileged",
|
|
// which looks like a bug (--privileged on the container should
|
|
// disable apparmor, seccomp, and selinux); see the code at:
|
|
// https://github.com/moby/moby/blob/46cdcd206c56172b95ba5c77b827a722dab426c5/daemon/exec_linux.go#L32-L40
|
|
// expectedProfile: unconfinedAppArmorProfile,
|
|
},
|
|
}
|
|
|
|
cfg := &configStore{}
|
|
d := &Daemon{}
|
|
d.configStore.Store(cfg)
|
|
|
|
// Currently, `docker exec --privileged` inherits the Privileged configuration
|
|
// of the container, and does not disable AppArmor.
|
|
// See https://github.com/moby/moby/pull/31773#discussion_r105586900
|
|
//
|
|
// This behavior may change in future, but to verify the current behavior,
|
|
// we run the test both with "exec" and "exec --privileged", which should
|
|
// both give the same result.
|
|
for _, execPrivileged := range []bool{false, true} {
|
|
for _, tc := range tests {
|
|
doc := tc.doc
|
|
if !appArmorEnabled {
|
|
// no profile should be set if the host does not support AppArmor
|
|
doc += " (apparmor disabled)"
|
|
tc.expectedProfile = ""
|
|
}
|
|
if execPrivileged {
|
|
doc += " (exec privileged)"
|
|
}
|
|
t.Run(doc, func(t *testing.T) {
|
|
c := &container.Container{
|
|
SecurityOptions: container.SecurityOptions{AppArmorProfile: tc.appArmorProfile},
|
|
HostConfig: &containertypes.HostConfig{
|
|
Privileged: tc.privileged,
|
|
},
|
|
}
|
|
ec := &container.ExecConfig{Container: c, Privileged: execPrivileged}
|
|
p := &specs.Process{}
|
|
|
|
err := d.execSetPlatformOpt(t.Context(), &cfg.Config, ec, p)
|
|
assert.NilError(t, err)
|
|
assert.Equal(t, p.ApparmorProfile, tc.expectedProfile)
|
|
})
|
|
}
|
|
}
|
|
}
|