Make libcontainer's CapabilitiesMask into a []string (Capabilities).
Docker-DCO-1.1-Signed-off-by: Victor Marmol <vmarmol@google.com> (github: vmarmol)
This commit is contained in:
parent
00ce30bc74
commit
92614928ce
9 changed files with 75 additions and 80 deletions
|
@ -109,12 +109,19 @@ func memorySwap(container *libcontainer.Container, context interface{}, value st
|
|||
}
|
||||
|
||||
func addCap(container *libcontainer.Container, context interface{}, value string) error {
|
||||
container.CapabilitiesMask[value] = true
|
||||
container.Capabilities = append(container.Capabilities, value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func dropCap(container *libcontainer.Container, context interface{}, value string) error {
|
||||
container.CapabilitiesMask[value] = false
|
||||
// If the capability is specified multiple times, remove all instances.
|
||||
for i, capability := range container.Capabilities {
|
||||
if capability == value {
|
||||
container.Capabilities = append(container.Capabilities[:i], container.Capabilities[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
// The capability wasn't found so we will drop it anyways.
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,19 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/dotcloud/docker/daemon/execdriver/native/template"
|
||||
"github.com/dotcloud/docker/pkg/libcontainer"
|
||||
)
|
||||
|
||||
// Checks whether the expected capability is specified in the capabilities.
|
||||
func hasCapability(expected string, capabilities []string) bool {
|
||||
for _, capability := range capabilities {
|
||||
if capability == expected {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestSetReadonlyRootFs(t *testing.T) {
|
||||
var (
|
||||
container = template.New()
|
||||
|
@ -39,10 +50,10 @@ func TestConfigurationsDoNotConflict(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !container1.CapabilitiesMask["NET_ADMIN"] {
|
||||
if !hasCapability("NET_ADMIN", container1.Capabilities) {
|
||||
t.Fatal("container one should have NET_ADMIN enabled")
|
||||
}
|
||||
if container2.CapabilitiesMask["NET_ADMIN"] {
|
||||
if hasCapability("NET_ADMIN", container2.Capabilities) {
|
||||
t.Fatal("container two should not have NET_ADMIN enabled")
|
||||
}
|
||||
}
|
||||
|
@ -138,10 +149,10 @@ func TestAddCap(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !container.CapabilitiesMask["MKNOD"] {
|
||||
if !hasCapability("MKNOD", container.Capabilities) {
|
||||
t.Fatal("container should have MKNOD enabled")
|
||||
}
|
||||
if !container.CapabilitiesMask["SYS_ADMIN"] {
|
||||
if !hasCapability("SYS_ADMIN", container.Capabilities) {
|
||||
t.Fatal("container should have SYS_ADMIN enabled")
|
||||
}
|
||||
}
|
||||
|
@ -154,14 +165,12 @@ func TestDropCap(t *testing.T) {
|
|||
}
|
||||
)
|
||||
// enabled all caps like in privileged mode
|
||||
for key := range container.CapabilitiesMask {
|
||||
container.CapabilitiesMask[key] = true
|
||||
}
|
||||
container.Capabilities = libcontainer.GetAllCapabilities()
|
||||
if err := ParseConfiguration(container, nil, opts); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if container.CapabilitiesMask["MKNOD"] {
|
||||
if hasCapability("MKNOD", container.Capabilities) {
|
||||
t.Fatal("container should not have MKNOD enabled")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,9 +98,7 @@ func (d *driver) createNetwork(container *libcontainer.Container, c *execdriver.
|
|||
}
|
||||
|
||||
func (d *driver) setPrivileged(container *libcontainer.Container) error {
|
||||
for key := range container.CapabilitiesMask {
|
||||
container.CapabilitiesMask[key] = true
|
||||
}
|
||||
container.Capabilities = libcontainer.GetAllCapabilities()
|
||||
container.Cgroups.DeviceAccess = true
|
||||
|
||||
delete(container.Context, "restrictions")
|
||||
|
|
|
@ -9,28 +9,13 @@ import (
|
|||
// New returns the docker default configuration for libcontainer
|
||||
func New() *libcontainer.Container {
|
||||
container := &libcontainer.Container{
|
||||
CapabilitiesMask: map[string]bool{
|
||||
"SETPCAP": false,
|
||||
"SYS_MODULE": false,
|
||||
"SYS_RAWIO": false,
|
||||
"SYS_PACCT": false,
|
||||
"SYS_ADMIN": false,
|
||||
"SYS_NICE": false,
|
||||
"SYS_RESOURCE": false,
|
||||
"SYS_TIME": false,
|
||||
"SYS_TTY_CONFIG": false,
|
||||
"AUDIT_WRITE": false,
|
||||
"AUDIT_CONTROL": false,
|
||||
"MAC_OVERRIDE": false,
|
||||
"MAC_ADMIN": false,
|
||||
"NET_ADMIN": false,
|
||||
"MKNOD": true,
|
||||
"SYSLOG": false,
|
||||
"SETUID": true,
|
||||
"SETGID": true,
|
||||
"CHOWN": true,
|
||||
"NET_RAW": true,
|
||||
"DAC_OVERRIDE": true,
|
||||
Capabilities: []string{
|
||||
"MKNOD",
|
||||
"SETUID",
|
||||
"SETGID",
|
||||
"CHOWN",
|
||||
"NET_RAW",
|
||||
"DAC_OVERRIDE",
|
||||
},
|
||||
Namespaces: map[string]bool{
|
||||
"NEWNS": true,
|
||||
|
|
|
@ -11,19 +11,19 @@ type Context map[string]string
|
|||
// Container defines configuration options for how a
|
||||
// container is setup inside a directory and how a process should be executed
|
||||
type Container struct {
|
||||
Hostname string `json:"hostname,omitempty"` // hostname
|
||||
ReadonlyFs bool `json:"readonly_fs,omitempty"` // set the containers rootfs as readonly
|
||||
NoPivotRoot bool `json:"no_pivot_root,omitempty"` // this can be enabled if you are running in ramdisk
|
||||
User string `json:"user,omitempty"` // user to execute the process as
|
||||
WorkingDir string `json:"working_dir,omitempty"` // current working directory
|
||||
Env []string `json:"environment,omitempty"` // environment to set
|
||||
Tty bool `json:"tty,omitempty"` // setup a proper tty or not
|
||||
Namespaces map[string]bool `json:"namespaces,omitempty"` // namespaces to apply
|
||||
CapabilitiesMask map[string]bool `json:"capabilities_mask,omitempty"` // capabilities to drop
|
||||
Networks []*Network `json:"networks,omitempty"` // nil for host's network stack
|
||||
Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` // cgroups
|
||||
Context Context `json:"context,omitempty"` // generic context for specific options (apparmor, selinux)
|
||||
Mounts Mounts `json:"mounts,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"` // hostname
|
||||
ReadonlyFs bool `json:"readonly_fs,omitempty"` // set the containers rootfs as readonly
|
||||
NoPivotRoot bool `json:"no_pivot_root,omitempty"` // this can be enabled if you are running in ramdisk
|
||||
User string `json:"user,omitempty"` // user to execute the process as
|
||||
WorkingDir string `json:"working_dir,omitempty"` // current working directory
|
||||
Env []string `json:"environment,omitempty"` // environment to set
|
||||
Tty bool `json:"tty,omitempty"` // setup a proper tty or not
|
||||
Namespaces map[string]bool `json:"namespaces,omitempty"` // namespaces to apply
|
||||
Capabilities []string `json:"capabilities,omitempty"` // capabilities given to the container
|
||||
Networks []*Network `json:"networks,omitempty"` // nil for host's network stack
|
||||
Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` // cgroups
|
||||
Context Context `json:"context,omitempty"` // generic context for specific options (apparmor, selinux)
|
||||
Mounts Mounts `json:"mounts,omitempty"`
|
||||
}
|
||||
|
||||
// Network defines configuration for a container's networking stack
|
||||
|
|
|
@ -24,24 +24,9 @@
|
|||
"mtu": 1500
|
||||
}
|
||||
],
|
||||
"capabilities_mask": {
|
||||
"SYSLOG": false,
|
||||
"MKNOD": true,
|
||||
"NET_ADMIN": false,
|
||||
"MAC_ADMIN": false,
|
||||
"MAC_OVERRIDE": false,
|
||||
"AUDIT_CONTROL": false,
|
||||
"AUDIT_WRITE": false,
|
||||
"SYS_TTY_CONFIG": false,
|
||||
"SETPCAP": false,
|
||||
"SYS_MODULE": false,
|
||||
"SYS_RAWIO": false,
|
||||
"SYS_PACCT": false,
|
||||
"SYS_ADMIN": false,
|
||||
"SYS_NICE": false,
|
||||
"SYS_RESOURCE": false,
|
||||
"SYS_TIME": false
|
||||
},
|
||||
"capabilities": [
|
||||
"MKNOD"
|
||||
],
|
||||
"cgroups": {
|
||||
"name": "docker-koye",
|
||||
"parent": "docker"
|
||||
|
|
|
@ -6,6 +6,16 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
// Checks whether the expected capability is specified in the capabilities.
|
||||
func hasCapability(expected string, capabilities []string) bool {
|
||||
for _, capability := range capabilities {
|
||||
if capability == expected {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestContainerJsonFormat(t *testing.T) {
|
||||
f, err := os.Open("container.json")
|
||||
if err != nil {
|
||||
|
@ -37,22 +47,17 @@ func TestContainerJsonFormat(t *testing.T) {
|
|||
t.Fail()
|
||||
}
|
||||
|
||||
if _, exists := container.CapabilitiesMask["SYS_ADMIN"]; !exists {
|
||||
t.Log("capabilities mask should contain SYS_ADMIN")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if container.CapabilitiesMask["SYS_ADMIN"] {
|
||||
if hasCapability("SYS_ADMIN", container.Capabilities) {
|
||||
t.Log("SYS_ADMIN should not be enabled in capabilities mask")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if !container.CapabilitiesMask["MKNOD"] {
|
||||
if !hasCapability("MKNOD", container.Capabilities) {
|
||||
t.Log("MKNOD should be enabled in capabilities mask")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if container.CapabilitiesMask["SYS_CHROOT"] {
|
||||
if hasCapability("SYS_CHROOT", container.Capabilities) {
|
||||
t.Log("capabilities mask should not contain SYS_CHROOT")
|
||||
t.Fail()
|
||||
}
|
||||
|
|
|
@ -26,14 +26,12 @@ func DropCapabilities(container *libcontainer.Container) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// getCapabilitiesMask returns the capabilities that should not be dropped by the container.
|
||||
// getEnabledCapabilities returns the capabilities that should not be dropped by the container.
|
||||
func getEnabledCapabilities(container *libcontainer.Container) []capability.Cap {
|
||||
keep := []capability.Cap{}
|
||||
for key, enabled := range container.CapabilitiesMask {
|
||||
if enabled {
|
||||
if c := libcontainer.GetCapability(key); c != nil {
|
||||
keep = append(keep, c.Value)
|
||||
}
|
||||
for _, capability := range container.Capabilities {
|
||||
if c := libcontainer.GetCapability(capability); c != nil {
|
||||
keep = append(keep, c.Value)
|
||||
}
|
||||
}
|
||||
return keep
|
||||
|
|
|
@ -123,6 +123,14 @@ func GetCapability(key string) *Capability {
|
|||
return nil
|
||||
}
|
||||
|
||||
func GetAllCapabilities() []string {
|
||||
output := make([]string, len(capabilityList))
|
||||
for i, capability := range capabilityList {
|
||||
output[i] = capability.String()
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
// Contains returns true if the specified Capability is
|
||||
// in the slice
|
||||
func (c Capabilities) Contains(capp string) bool {
|
||||
|
|
Loading…
Add table
Reference in a new issue