2021-02-04 19:46:20 +00:00
|
|
|
package daemon // import "github.com/docker/docker/daemon"
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
coci "github.com/containerd/containerd/oci"
|
2021-08-21 22:46:07 +00:00
|
|
|
containertypes "github.com/docker/docker/api/types/container"
|
2021-02-04 19:46:20 +00:00
|
|
|
"github.com/docker/docker/container"
|
2021-06-07 11:44:32 +00:00
|
|
|
dconfig "github.com/docker/docker/daemon/config"
|
2021-08-21 22:46:07 +00:00
|
|
|
"github.com/docker/docker/oci"
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
"github.com/docker/docker/pkg/sysinfo"
|
2021-02-04 19:46:20 +00:00
|
|
|
"github.com/docker/docker/profiles/seccomp"
|
|
|
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
|
|
"gotest.tools/v3/assert"
|
|
|
|
)
|
|
|
|
|
|
|
|
func TestWithSeccomp(t *testing.T) {
|
|
|
|
type expected struct {
|
|
|
|
daemon *Daemon
|
|
|
|
c *container.Container
|
|
|
|
inSpec coci.Spec
|
|
|
|
outSpec coci.Spec
|
|
|
|
err string
|
|
|
|
comment string
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, x := range []expected{
|
|
|
|
{
|
|
|
|
comment: "unconfined seccompProfile runs unconfined",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: dconfig.SeccompProfileUnconfined},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: false,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
|
|
|
outSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "privileged container w/ custom profile runs unconfined",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: `{"defaultAction": "SCMP_ACT_LOG"}`},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: true,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
|
|
|
outSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "privileged container w/ default runs unconfined",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: ""},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: true,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
|
|
|
outSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "privileged container w/ daemon profile runs unconfined",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2023-04-14 07:27:20 +00:00
|
|
|
seccompProfile: []byte(`{"defaultAction": "SCMP_ACT_ERRNO"}`),
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: ""},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: true,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
|
|
|
outSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "custom profile when seccomp is disabled returns error",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: false},
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: `{"defaultAction": "SCMP_ACT_ERRNO"}`},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: false,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
|
|
|
outSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
err: "seccomp is not enabled in your kernel, cannot run a custom seccomp profile",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "empty profile name loads default profile",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: ""},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: false,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
outSpec: func() coci.Spec {
|
2021-08-21 22:46:07 +00:00
|
|
|
s := oci.DefaultLinuxSpec()
|
2021-02-04 19:46:20 +00:00
|
|
|
profile, _ := seccomp.GetDefaultProfile(&s)
|
|
|
|
s.Linux.Seccomp = profile
|
|
|
|
return s
|
|
|
|
}(),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "load container's profile",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: `{"defaultAction": "SCMP_ACT_ERRNO"}`},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: false,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
outSpec: func() coci.Spec {
|
2021-08-21 22:46:07 +00:00
|
|
|
s := oci.DefaultLinuxSpec()
|
2021-02-04 19:46:20 +00:00
|
|
|
profile := &specs.LinuxSeccomp{
|
|
|
|
DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_ERRNO"),
|
|
|
|
}
|
|
|
|
s.Linux.Seccomp = profile
|
|
|
|
return s
|
|
|
|
}(),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "load daemon's profile",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2023-04-14 07:27:20 +00:00
|
|
|
seccompProfile: []byte(`{"defaultAction": "SCMP_ACT_ERRNO"}`),
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: ""},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: false,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
outSpec: func() coci.Spec {
|
2021-08-21 22:46:07 +00:00
|
|
|
s := oci.DefaultLinuxSpec()
|
2021-02-04 19:46:20 +00:00
|
|
|
profile := &specs.LinuxSeccomp{
|
|
|
|
DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_ERRNO"),
|
|
|
|
}
|
|
|
|
s.Linux.Seccomp = profile
|
|
|
|
return s
|
|
|
|
}(),
|
|
|
|
},
|
|
|
|
{
|
|
|
|
comment: "load prioritise container profile over daemon's",
|
|
|
|
daemon: &Daemon{
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
sysInfo: &sysinfo.SysInfo{Seccomp: true},
|
2023-04-14 07:27:20 +00:00
|
|
|
seccompProfile: []byte(`{"defaultAction": "SCMP_ACT_ERRNO"}`),
|
2021-02-04 19:46:20 +00:00
|
|
|
},
|
|
|
|
c: &container.Container{
|
2023-04-14 07:27:20 +00:00
|
|
|
SecurityOptions: container.SecurityOptions{SeccompProfile: `{"defaultAction": "SCMP_ACT_LOG"}`},
|
2021-08-21 22:46:07 +00:00
|
|
|
HostConfig: &containertypes.HostConfig{
|
2021-02-04 19:46:20 +00:00
|
|
|
Privileged: false,
|
|
|
|
},
|
|
|
|
},
|
2021-08-21 22:46:07 +00:00
|
|
|
inSpec: oci.DefaultLinuxSpec(),
|
2021-02-04 19:46:20 +00:00
|
|
|
outSpec: func() coci.Spec {
|
2021-08-21 22:46:07 +00:00
|
|
|
s := oci.DefaultLinuxSpec()
|
2021-02-04 19:46:20 +00:00
|
|
|
profile := &specs.LinuxSeccomp{
|
|
|
|
DefaultAction: specs.LinuxSeccompAction("SCMP_ACT_LOG"),
|
|
|
|
}
|
|
|
|
s.Linux.Seccomp = profile
|
|
|
|
return s
|
|
|
|
}(),
|
|
|
|
},
|
|
|
|
} {
|
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects
information about all cgroups on the host, networking, AppArmor, Seccomp, etc.
While looking at our code, I noticed that various parts in the code call this
function, potentially even _multiple times_ per container, for example, it is
called from:
- `verifyPlatformContainerSettings()`
- `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured
- in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit`
Given that this information is not expected to change during the daemon's
lifecycle, and various information coming from this (such as seccomp and
apparmor status) was already cached, we may as well load it once, and cache
the results in the daemon instance.
This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that
it's only executed once for the daemon's lifecycle.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-01-07 11:54:47 +00:00
|
|
|
x := x
|
2021-02-04 19:46:20 +00:00
|
|
|
t.Run(x.comment, func(t *testing.T) {
|
|
|
|
opts := WithSeccomp(x.daemon, x.c)
|
|
|
|
err := opts(nil, nil, nil, &x.inSpec)
|
|
|
|
|
|
|
|
assert.DeepEqual(t, x.inSpec, x.outSpec)
|
|
|
|
if x.err != "" {
|
|
|
|
assert.Error(t, err, x.err)
|
|
|
|
} else {
|
|
|
|
assert.NilError(t, err)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|