drivers/docker+exec+java: disable net_raw capability by default

The default Linux Capabilities set enabled by the docker, exec, and
java task drivers includes CAP_NET_RAW (for making ping just work),
which has the side affect of opening an ARP DoS/MiTM attack between
tasks using bridge networking on the same host network.

https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities

This PR disables CAP_NET_RAW for the docker, exec, and java task
drivers. The previous behavior can be restored for docker using the
allow_caps docker plugin configuration option.

A future version of nomad will enable similar configurability for the
exec and java task drivers.
This commit is contained in:
Seth Hoenig
2021-05-12 13:22:09 -07:00
committed by Michael Schurter
parent 1235684be7
commit 003d68fe6d
9 changed files with 416 additions and 69 deletions

View File

@@ -23,6 +23,7 @@ import (
cstructs "github.com/hashicorp/nomad/client/structs"
"github.com/hashicorp/nomad/plugins/drivers"
"github.com/kr/pty"
"github.com/syndtr/gocapability/capability"
shelpers "github.com/hashicorp/nomad/helper/stats"
)
@@ -684,3 +685,23 @@ func makeExecutable(binPath string) error {
}
return nil
}
// SupportedCaps returns a list of all supported capabilities in kernel.
func SupportedCaps(allowNetRaw bool) []string {
var allCaps []string
last := capability.CAP_LAST_CAP
// workaround for RHEL6 which has no /proc/sys/kernel/cap_last_cap
if last == capability.Cap(63) {
last = capability.CAP_BLOCK_SUSPEND
}
for _, cap := range capability.List() {
if cap > last {
continue
}
if !allowNetRaw && cap == capability.CAP_NET_RAW {
continue
}
allCaps = append(allCaps, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
}
return allCaps
}

View File

@@ -32,7 +32,6 @@ import (
ldevices "github.com/opencontainers/runc/libcontainer/devices"
"github.com/opencontainers/runc/libcontainer/specconv"
lutils "github.com/opencontainers/runc/libcontainer/utils"
"github.com/syndtr/gocapability/capability"
"golang.org/x/sys/unix"
)
@@ -534,12 +533,12 @@ func (l *LibcontainerExecutor) handleExecWait(ch chan *waitResult, process *libc
}
func configureCapabilities(cfg *lconfigs.Config, command *ExecCommand) error {
// TODO: allow better control of these
// TODO(shoenig): allow better control of these
// use capabilities list as prior to adopting libcontainer in 0.9
allCaps := supportedCaps()
// match capabilities used in Nomad 0.8
if command.User == "root" {
allCaps := SupportedCaps(true)
cfg.Capabilities = &lconfigs.Capabilities{
Bounding: allCaps,
Permitted: allCaps,
@@ -548,6 +547,7 @@ func configureCapabilities(cfg *lconfigs.Config, command *ExecCommand) error {
Inheritable: nil,
}
} else {
allCaps := SupportedCaps(false)
cfg.Capabilities = &lconfigs.Capabilities{
Bounding: allCaps,
}
@@ -556,23 +556,6 @@ func configureCapabilities(cfg *lconfigs.Config, command *ExecCommand) error {
return nil
}
// supportedCaps returns a list of all supported capabilities in kernel
func supportedCaps() []string {
allCaps := []string{}
last := capability.CAP_LAST_CAP
// workaround for RHEL6 which has no /proc/sys/kernel/cap_last_cap
if last == capability.Cap(63) {
last = capability.CAP_BLOCK_SUSPEND
}
for _, cap := range capability.List() {
if cap > last {
continue
}
allCaps = append(allCaps, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
}
return allCaps
}
func configureNamespaces(pidMode, ipcMode string) lconfigs.Namespaces {
namespaces := lconfigs.Namespaces{{Type: lconfigs.NEWNS}}
if pidMode == IsolationModePrivate {

View File

@@ -478,7 +478,7 @@ func TestExecutor_Capabilities(t *testing.T) {
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapBnd: 0000003fffffdfff
CapAmb: 0000000000000000`,
},
{