//go:build linux package daemon import ( "context" "testing" "github.com/containerd/containerd/pkg/apparmor" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" specs "github.com/opencontainers/runtime-spec/specs-go" "gotest.tools/v3/assert" ) func TestExecSetPlatformOptAppArmor(t *testing.T) { appArmorEnabled := apparmor.HostSupports() 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 { tc := tc 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(context.Background(), &cfg.Config, ec, p) assert.NilError(t, err) assert.Equal(t, p.ApparmorProfile, tc.expectedProfile) }) } } }