Merge pull request #51 from crosbymichael/type-context

Strongly type context on the Config
This commit is contained in:
Victor Marmol 2014-06-24 20:29:07 -07:00
commit e49f5f4788
9 changed files with 464 additions and 27 deletions

View File

@ -51,12 +51,17 @@ type Config struct {
// placed into to limit the resources the container has available
Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"`
// Context is a generic key value format that allows for additional settings to be passed
// on the container's creation
// This is commonly used to specify apparmor profiles, selinux labels, and different restrictions
// placed on the container's processes
// TODO(vishh): Avoid overloading this field with params for different subsystems. Strongtype this.
Context map[string]string `json:"context,omitempty"`
// AppArmorProfile specifies the profile to apply to the process running in the container and is
// change at the time the process is execed
AppArmorProfile string `json:"apparmor_profile,omitempty"`
// ProcessLabel specifies the label to apply to the process running in the container. It is
// commonly used by selinux
ProcessLabel string `json:"process_label,omitempty"`
// RestrictSys will remount /proc/sys, /sys, and mask over sysrq-trigger as well as /proc/irq and
// /proc/bus
RestrictSys bool `json:"restrict_sys,omitempty"`
}
// Routes can be specified to create entries in the route table as the container is started

View File

@ -3,6 +3,7 @@ package libcontainer
import (
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/docker/libcontainer/devices"
@ -32,17 +33,27 @@ func containsDevice(expected *devices.Device, values []*devices.Device) bool {
return false
}
func TestConfigJsonFormat(t *testing.T) {
f, err := os.Open("sample_configs/attach_to_bridge.json")
func loadConfig(name string) (*Config, error) {
f, err := os.Open(filepath.Join("sample_configs", name))
if err != nil {
t.Fatal("Unable to open container.json")
return nil, err
}
defer f.Close()
var container *Config
if err := json.NewDecoder(f).Decode(&container); err != nil {
t.Fatalf("failed to decode container config: %s", err)
return nil, err
}
return container, nil
}
func TestConfigJsonFormat(t *testing.T) {
container, err := loadConfig("attach_to_bridge.json")
if err != nil {
t.Fatal(err)
}
if container.Hostname != "koye" {
t.Log("hostname is not set")
t.Fail()
@ -111,8 +122,39 @@ func TestConfigJsonFormat(t *testing.T) {
for _, d := range devices.DefaultSimpleDevices {
if !containsDevice(d, container.MountConfig.DeviceNodes) {
t.Logf("expected defice configuration for %s", d.Path)
t.Logf("expected device configuration for %s", d.Path)
t.Fail()
}
}
if !container.RestrictSys {
t.Log("expected restrict sys to be true")
t.Fail()
}
}
func TestApparmorProfile(t *testing.T) {
container, err := loadConfig("apparmor.json")
if err != nil {
t.Fatal(err)
}
if container.AppArmorProfile != "docker-default" {
t.Fatalf("expected apparmor profile to be docker-default but received %q", container.AppArmorProfile)
}
}
func TestSelinuxLabels(t *testing.T) {
container, err := loadConfig("selinux.json")
if err != nil {
t.Fatal(err)
}
label := "system_u:system_r:svirt_lxc_net_t:s0:c164,c475"
if container.ProcessLabel != label {
t.Fatalf("expected process label %q but received %q", label, container.ProcessLabel)
}
if container.MountConfig.MountLabel != label {
t.Fatalf("expected mount label %q but received %q", label, container.MountConfig.MountLabel)
}
}

View File

@ -2,6 +2,7 @@ package mount
import (
"errors"
"github.com/docker/libcontainer/devices"
)

View File

@ -41,8 +41,8 @@ func NsEnter(container *libcontainer.Config, nspid int, args []string) error {
return err
}
if process_label, ok := container.Context["process_label"]; ok {
if err := label.SetProcessLabel(process_label); err != nil {
if container.ProcessLabel != "" {
if err := label.SetProcessLabel(container.ProcessLabel); err != nil {
return err
}
}

View File

@ -74,6 +74,7 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn
(*mount.MountConfig)(container.MountConfig)); err != nil {
return fmt.Errorf("setup mount namespace %s", err)
}
if container.Hostname != "" {
if err := system.Sethostname(container.Hostname); err != nil {
return fmt.Errorf("sethostname %s", err)
@ -82,13 +83,16 @@ func Init(container *libcontainer.Config, uncleanRootfs, consolePath string, syn
runtime.LockOSThread()
if err := apparmor.ApplyProfile(container.Context["apparmor_profile"]); err != nil {
return fmt.Errorf("set apparmor profile %s: %s", container.Context["apparmor_profile"], err)
if err := apparmor.ApplyProfile(container.AppArmorProfile); err != nil {
return fmt.Errorf("set apparmor profile %s: %s", container.AppArmorProfile, err)
}
if err := label.SetProcessLabel(container.Context["process_label"]); err != nil {
if err := label.SetProcessLabel(container.ProcessLabel); err != nil {
return fmt.Errorf("set process label %s", err)
}
if container.Context["restrictions"] != "" {
// TODO: (crosbymichael) make this configurable at the Config level
if container.RestrictSys {
if err := restrict.Restrict("proc/sys", "proc/sysrq-trigger", "proc/irq", "proc/bus", "sys"); err != nil {
return err
}

View File

@ -0,0 +1,196 @@
{
"capabilities": [
"CHOWN",
"DAC_OVERRIDE",
"FOWNER",
"MKNOD",
"NET_RAW",
"SETGID",
"SETUID",
"SETFCAP",
"SETPCAP",
"NET_BIND_SERVICE",
"SYS_CHROOT",
"KILL"
],
"cgroups": {
"allowed_devices": [
{
"cgroup_permissions": "m",
"major_number": -1,
"minor_number": -1,
"type": 99
},
{
"cgroup_permissions": "m",
"major_number": -1,
"minor_number": -1,
"type": 98
},
{
"cgroup_permissions": "rwm",
"major_number": 5,
"minor_number": 1,
"path": "/dev/console",
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 4,
"path": "/dev/tty0",
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 4,
"minor_number": 1,
"path": "/dev/tty1",
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 136,
"minor_number": -1,
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 5,
"minor_number": 2,
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 10,
"minor_number": 200,
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 3,
"path": "/dev/null",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 5,
"path": "/dev/zero",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 7,
"path": "/dev/full",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 5,
"path": "/dev/tty",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 9,
"path": "/dev/urandom",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 8,
"path": "/dev/random",
"type": 99
}
],
"name": "docker-koye",
"parent": "docker"
},
"restrict_sys": true,
"apparmor_profile": "docker-default",
"mount_config": {
"device_nodes": [
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 3,
"path": "/dev/null",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 5,
"path": "/dev/zero",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 7,
"path": "/dev/full",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 5,
"path": "/dev/tty",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 9,
"path": "/dev/urandom",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 8,
"path": "/dev/random",
"type": 99
}
]
},
"environment": [
"HOME=/",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME=koye",
"TERM=xterm"
],
"hostname": "koye",
"namespaces": {
"NEWIPC": true,
"NEWNET": true,
"NEWNS": true,
"NEWPID": true,
"NEWUTS": true
},
"networks": [
{
"address": "127.0.0.1/0",
"gateway": "localhost",
"mtu": 1500,
"type": "loopback"
}
],
"tty": true,
"user": "daemon"
}

View File

@ -116,11 +116,7 @@
"name": "docker-koye",
"parent": "docker"
},
"context": {
"mount_label": "",
"process_label": "",
"restrictions": "true"
},
"restrict_sys": true,
"mount_config": {
"device_nodes": [
{

View File

@ -116,11 +116,7 @@
"name": "docker-koye",
"parent": "docker"
},
"context": {
"mount_label": "",
"process_label": "",
"restrictions": "true"
},
"restrict_sys": true,
"mount_config": {
"device_nodes": [
{

197
sample_configs/selinux.json Normal file
View File

@ -0,0 +1,197 @@
{
"capabilities": [
"CHOWN",
"DAC_OVERRIDE",
"FOWNER",
"MKNOD",
"NET_RAW",
"SETGID",
"SETUID",
"SETFCAP",
"SETPCAP",
"NET_BIND_SERVICE",
"SYS_CHROOT",
"KILL"
],
"cgroups": {
"allowed_devices": [
{
"cgroup_permissions": "m",
"major_number": -1,
"minor_number": -1,
"type": 99
},
{
"cgroup_permissions": "m",
"major_number": -1,
"minor_number": -1,
"type": 98
},
{
"cgroup_permissions": "rwm",
"major_number": 5,
"minor_number": 1,
"path": "/dev/console",
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 4,
"path": "/dev/tty0",
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 4,
"minor_number": 1,
"path": "/dev/tty1",
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 136,
"minor_number": -1,
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 5,
"minor_number": 2,
"type": 99
},
{
"cgroup_permissions": "rwm",
"major_number": 10,
"minor_number": 200,
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 3,
"path": "/dev/null",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 5,
"path": "/dev/zero",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 7,
"path": "/dev/full",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 5,
"path": "/dev/tty",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 9,
"path": "/dev/urandom",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 8,
"path": "/dev/random",
"type": 99
}
],
"name": "docker-koye",
"parent": "docker"
},
"restrict_sys": true,
"process_label": "system_u:system_r:svirt_lxc_net_t:s0:c164,c475",
"mount_config": {
"mount_label": "system_u:system_r:svirt_lxc_net_t:s0:c164,c475",
"device_nodes": [
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 3,
"path": "/dev/null",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 5,
"path": "/dev/zero",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 7,
"path": "/dev/full",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 5,
"path": "/dev/tty",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 9,
"path": "/dev/urandom",
"type": 99
},
{
"cgroup_permissions": "rwm",
"file_mode": 438,
"major_number": 1,
"minor_number": 8,
"path": "/dev/random",
"type": 99
}
]
},
"environment": [
"HOME=/",
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"HOSTNAME=koye",
"TERM=xterm"
],
"hostname": "koye",
"namespaces": {
"NEWIPC": true,
"NEWNET": true,
"NEWNS": true,
"NEWPID": true,
"NEWUTS": true
},
"networks": [
{
"address": "127.0.0.1/0",
"gateway": "localhost",
"mtu": 1500,
"type": "loopback"
}
],
"tty": true,
"user": "daemon"
}