Merge pull request #41 from vishh/refactoring
Refactoring libcontainer to avoid cyclic dependencies in the future.
This commit is contained in:
commit
e783cac215
52
container.go
52
container.go
|
@ -2,25 +2,22 @@ package libcontainer
|
|||
|
||||
import (
|
||||
"github.com/docker/libcontainer/cgroups"
|
||||
"github.com/docker/libcontainer/devices"
|
||||
"github.com/docker/libcontainer/mount"
|
||||
"github.com/docker/libcontainer/network"
|
||||
)
|
||||
|
||||
// Context is a generic key value pair that allows arbatrary data to be sent
|
||||
type Context map[string]string
|
||||
type MountConfig mount.MountConfig
|
||||
|
||||
type Network network.Network
|
||||
|
||||
// Container defines configuration options for executing a process inside a contained environment
|
||||
type Container struct {
|
||||
// Mount specific options.
|
||||
MountConfig *MountConfig `json:"mount_config,omitempty"`
|
||||
|
||||
// Hostname optionally sets the container's hostname if provided
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
|
||||
// ReadonlyFs will remount the container's rootfs as readonly where only externally mounted
|
||||
// bind mounts are writtable
|
||||
ReadonlyFs bool `json:"readonly_fs,omitempty"`
|
||||
|
||||
// NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs
|
||||
// This is a common option when the container is running in ramdisk
|
||||
NoPivotRoot bool `json:"no_pivot_root,omitempty"`
|
||||
|
||||
// User will set the uid and gid of the executing process running inside the container
|
||||
User string `json:"user,omitempty"`
|
||||
|
||||
|
@ -58,37 +55,8 @@ type Container struct {
|
|||
// on the container's creation
|
||||
// This is commonly used to specify apparmor profiles, selinux labels, and different restrictions
|
||||
// placed on the container's processes
|
||||
Context Context `json:"context,omitempty"`
|
||||
|
||||
// Mounts specify additional source and destination paths that will be mounted inside the container's
|
||||
// rootfs and mount namespace if specified
|
||||
Mounts Mounts `json:"mounts,omitempty"`
|
||||
|
||||
// The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well!
|
||||
DeviceNodes []*devices.Device `json:"device_nodes,omitempty"`
|
||||
}
|
||||
|
||||
// Network defines configuration for a container's networking stack
|
||||
//
|
||||
// The network configuration can be omited from a container causing the
|
||||
// container to be setup with the host's networking stack
|
||||
type Network struct {
|
||||
// Type sets the networks type, commonly veth and loopback
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// Context is a generic key value format for setting additional options that are specific to
|
||||
// the network type
|
||||
Context Context `json:"context,omitempty"`
|
||||
|
||||
// Address contains the IP and mask to set on the network interface
|
||||
Address string `json:"address,omitempty"`
|
||||
|
||||
// Gateway sets the gateway address that is used as the default for the interface
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
|
||||
// Mtu sets the mtu value for the interface and will be mirrored on both the host and
|
||||
// container's interfaces if a pair is created, specifically in the case of type veth
|
||||
Mtu int `json:"mtu,omitempty"`
|
||||
// TODO(vishh): Avoid overloading this field with params for different subsystems. Strongtype this.
|
||||
Context map[string]string `json:"context,omitempty"`
|
||||
}
|
||||
|
||||
// Routes can be specified to create entries in the route table as the container is started
|
||||
|
|
|
@ -4,6 +4,8 @@ import (
|
|||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/libcontainer/devices"
|
||||
)
|
||||
|
||||
// Checks whether the expected capability is specified in the capabilities.
|
||||
|
@ -16,6 +18,20 @@ func contains(expected string, values []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func containsDevice(expected *devices.Device, values []*devices.Device) bool {
|
||||
for _, d := range values {
|
||||
if d.Path == expected.Path &&
|
||||
d.CgroupPermissions == expected.CgroupPermissions &&
|
||||
d.FileMode == expected.FileMode &&
|
||||
d.MajorNumber == expected.MajorNumber &&
|
||||
d.MinorNumber == expected.MinorNumber &&
|
||||
d.Type == expected.Type {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestContainerJsonFormat(t *testing.T) {
|
||||
f, err := os.Open("sample_configs/attach_to_bridge.json")
|
||||
if err != nil {
|
||||
|
@ -61,4 +77,42 @@ func TestContainerJsonFormat(t *testing.T) {
|
|||
t.Log("capabilities mask should contain SYS_CHROOT")
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
for _, n := range container.Networks {
|
||||
if n.Type == "veth" {
|
||||
if n.Bridge != "docker0" {
|
||||
t.Logf("veth bridge should be docker0 but received %q", n.Bridge)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if n.Address != "172.17.0.101/16" {
|
||||
t.Logf("veth address should be 172.17.0.101/61 but received %q", n.Address)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if n.VethPrefix != "veth" {
|
||||
t.Logf("veth prefix should be veth but received %q", n.VethPrefix)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if n.Gateway != "172.17.42.1" {
|
||||
t.Logf("veth gateway should be 172.17.42.1 but received %q", n.Gateway)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
if n.Mtu != 1500 {
|
||||
t.Logf("veth mtu should be 1500 but received %d", n.Mtu)
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
for _, d := range devices.DefaultSimpleDevices {
|
||||
if !containsDevice(d, container.MountConfig.DeviceNodes) {
|
||||
t.Logf("expected defice configuration for %s", d.Path)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libcontainer"
|
||||
"github.com/docker/libcontainer/label"
|
||||
"github.com/docker/libcontainer/mount/nodes"
|
||||
"github.com/dotcloud/docker/pkg/symlink"
|
||||
|
@ -28,12 +27,12 @@ type mount struct {
|
|||
|
||||
// InitializeMountNamespace setups up the devices, mount points, and filesystems for use inside a
|
||||
// new mount namepsace
|
||||
func InitializeMountNamespace(rootfs, console string, container *libcontainer.Container) error {
|
||||
func InitializeMountNamespace(rootfs, console string, mountConfig *MountConfig) error {
|
||||
var (
|
||||
err error
|
||||
flag = syscall.MS_PRIVATE
|
||||
)
|
||||
if container.NoPivotRoot {
|
||||
if mountConfig.NoPivotRoot {
|
||||
flag = syscall.MS_SLAVE
|
||||
}
|
||||
if err := system.Mount("", "/", "", uintptr(flag|syscall.MS_REC), ""); err != nil {
|
||||
|
@ -42,16 +41,16 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
|
|||
if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil {
|
||||
return fmt.Errorf("mouting %s as bind %s", rootfs, err)
|
||||
}
|
||||
if err := mountSystem(rootfs, container); err != nil {
|
||||
if err := mountSystem(rootfs, mountConfig); err != nil {
|
||||
return fmt.Errorf("mount system %s", err)
|
||||
}
|
||||
if err := setupBindmounts(rootfs, container.Mounts); err != nil {
|
||||
if err := setupBindmounts(rootfs, mountConfig.Mounts); err != nil {
|
||||
return fmt.Errorf("bind mounts %s", err)
|
||||
}
|
||||
if err := nodes.CreateDeviceNodes(rootfs, container.DeviceNodes); err != nil {
|
||||
if err := nodes.CreateDeviceNodes(rootfs, mountConfig.DeviceNodes); err != nil {
|
||||
return fmt.Errorf("create device nodes %s", err)
|
||||
}
|
||||
if err := SetupPtmx(rootfs, console, container.Context["mount_label"]); err != nil {
|
||||
if err := SetupPtmx(rootfs, console, mountConfig.MountLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := setupDevSymlinks(rootfs); err != nil {
|
||||
|
@ -61,7 +60,7 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
|
|||
return fmt.Errorf("chdir into %s %s", rootfs, err)
|
||||
}
|
||||
|
||||
if container.NoPivotRoot {
|
||||
if mountConfig.NoPivotRoot {
|
||||
err = MsMoveRoot(rootfs)
|
||||
} else {
|
||||
err = PivotRoot(rootfs)
|
||||
|
@ -70,7 +69,7 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
|
|||
return err
|
||||
}
|
||||
|
||||
if container.ReadonlyFs {
|
||||
if mountConfig.ReadonlyFs {
|
||||
if err := SetReadonly(); err != nil {
|
||||
return fmt.Errorf("set readonly %s", err)
|
||||
}
|
||||
|
@ -83,8 +82,8 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
|
|||
|
||||
// mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts
|
||||
// inside the mount namespace
|
||||
func mountSystem(rootfs string, container *libcontainer.Container) error {
|
||||
for _, m := range newSystemMounts(rootfs, container.Context["mount_label"], container.Mounts) {
|
||||
func mountSystem(rootfs string, mountConfig *MountConfig) error {
|
||||
for _, m := range newSystemMounts(rootfs, mountConfig.MountLabel, mountConfig.Mounts) {
|
||||
if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) {
|
||||
return fmt.Errorf("mkdirall %s %s", m.path, err)
|
||||
}
|
||||
|
@ -145,7 +144,7 @@ func setupDevSymlinks(rootfs string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error {
|
||||
func setupBindmounts(rootfs string, bindMounts Mounts) error {
|
||||
for _, m := range bindMounts.OfType("bind") {
|
||||
var (
|
||||
flags = syscall.MS_BIND | syscall.MS_REC
|
||||
|
@ -188,7 +187,7 @@ func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error {
|
|||
|
||||
// TODO: this is crappy right now and should be cleaned up with a better way of handling system and
|
||||
// standard bind mounts allowing them to be more dynamic
|
||||
func newSystemMounts(rootfs, mountLabel string, mounts libcontainer.Mounts) []mount {
|
||||
func newSystemMounts(rootfs, mountLabel string, mounts Mounts) []mount {
|
||||
systemMounts := []mount{
|
||||
{source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags},
|
||||
{source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: defaultMountFlags},
|
||||
|
|
|
@ -3,10 +3,11 @@
|
|||
package nodes
|
||||
|
||||
import (
|
||||
"github.com/docker/libcontainer"
|
||||
"errors"
|
||||
|
||||
"github.com/docker/libcontainer/devices"
|
||||
)
|
||||
|
||||
func CreateDeviceNodes(rootfs string, nodesToCreate []*devices.Device) error {
|
||||
return libcontainer.ErrUnsupported
|
||||
return errors.New("Unsupported method")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package mount
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/docker/libcontainer/devices"
|
||||
)
|
||||
|
||||
type MountConfig struct {
|
||||
// NoPivotRoot will use MS_MOVE and a chroot to jail the process into the container's rootfs
|
||||
// This is a common option when the container is running in ramdisk
|
||||
NoPivotRoot bool `json:"no_pivot_root,omitempty"`
|
||||
|
||||
// ReadonlyFs will remount the container's rootfs as readonly where only externally mounted
|
||||
// bind mounts are writtable
|
||||
ReadonlyFs bool `json:"readonly_fs,omitempty"`
|
||||
|
||||
// Mounts specify additional source and destination paths that will be mounted inside the container's
|
||||
// rootfs and mount namespace if specified
|
||||
Mounts Mounts `json:"mounts,omitempty"`
|
||||
|
||||
// The device nodes that should be automatically created within the container upon container start. Note, make sure that the node is marked as allowed in the cgroup as well!
|
||||
DeviceNodes []*devices.Device `json:"device_nodes,omitempty"`
|
||||
|
||||
MountLabel string `json:"mount_label,omitempty"`
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Source string `json:"source,omitempty"` // Source path, in the host namespace
|
||||
Destination string `json:"destination,omitempty"` // Destination path, in the container
|
||||
Writable bool `json:"writable,omitempty"`
|
||||
Private bool `json:"private,omitempty"`
|
||||
}
|
||||
|
||||
type Mounts []Mount
|
||||
|
||||
var ErrUnsupported = errors.New("Unsupported method")
|
||||
|
||||
func (s Mounts) OfType(t string) Mounts {
|
||||
out := Mounts{}
|
||||
for _, m := range s {
|
||||
if m.Type == t {
|
||||
out = append(out, m)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
|
@ -15,6 +15,8 @@ import (
|
|||
"github.com/dotcloud/docker/pkg/system"
|
||||
)
|
||||
|
||||
// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work.
|
||||
// Move this to libcontainer package.
|
||||
// Exec performes setup outside of a namespace so that a container can be
|
||||
// executed. Exec is a high level function for working with container namespaces.
|
||||
func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
|
||||
|
@ -149,13 +151,13 @@ func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveC
|
|||
// InitializeNetworking creates the container's network stack outside of the namespace and moves
|
||||
// interfaces into the container's net namespaces if necessary
|
||||
func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *SyncPipe) error {
|
||||
context := libcontainer.Context{}
|
||||
context := map[string]string{}
|
||||
for _, config := range container.Networks {
|
||||
strategy, err := network.GetStrategy(config.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := strategy.Create(config, nspid, context); err != nil {
|
||||
if err := strategy.Create((*network.Network)(config), nspid, context); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +169,7 @@ func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *Sy
|
|||
func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
|
||||
for key, enabled := range namespaces {
|
||||
if enabled {
|
||||
if ns := libcontainer.GetNamespace(key); ns != nil {
|
||||
if ns := GetNamespace(key); ns != nil {
|
||||
flag |= ns.Value
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import (
|
|||
"github.com/dotcloud/docker/pkg/user"
|
||||
)
|
||||
|
||||
// TODO(vishh): This is part of the libcontainer API and it does much more than just namespaces related work.
|
||||
// Move this to libcontainer package.
|
||||
// Init is the init process that first runs inside a new namespace to setup mounts, users, networking,
|
||||
// and other options required for the new container.
|
||||
func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
|
||||
|
@ -67,7 +69,9 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string,
|
|||
|
||||
label.Init()
|
||||
|
||||
if err := mount.InitializeMountNamespace(rootfs, consolePath, container); err != nil {
|
||||
if err := mount.InitializeMountNamespace(rootfs,
|
||||
consolePath,
|
||||
(*mount.MountConfig)(container.MountConfig)); err != nil {
|
||||
return fmt.Errorf("setup mount namespace %s", err)
|
||||
}
|
||||
if container.Hostname != "" {
|
||||
|
@ -157,14 +161,14 @@ func SetupUser(u string) error {
|
|||
// setupVethNetwork uses the Network config if it is not nil to initialize
|
||||
// the new veth interface inside the container for use by changing the name to eth0
|
||||
// setting the MTU and IP address along with the default gateway
|
||||
func setupNetwork(container *libcontainer.Container, context libcontainer.Context) error {
|
||||
func setupNetwork(container *libcontainer.Container, context map[string]string) error {
|
||||
for _, config := range container.Networks {
|
||||
strategy, err := network.GetStrategy(config.Type)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err1 := strategy.Initialize(config, context)
|
||||
err1 := strategy.Initialize((*network.Network)(config), context)
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
|
@ -193,7 +197,7 @@ func FinalizeNamespace(container *libcontainer.Container) error {
|
|||
}
|
||||
|
||||
// drop capabilities in bounding set before changing user
|
||||
if err := capabilities.DropBoundingSet(container); err != nil {
|
||||
if err := capabilities.DropBoundingSet(container.Capabilities); err != nil {
|
||||
return fmt.Errorf("drop bounding set %s", err)
|
||||
}
|
||||
|
||||
|
@ -211,7 +215,7 @@ func FinalizeNamespace(container *libcontainer.Container) error {
|
|||
}
|
||||
|
||||
// drop all other capabilities
|
||||
if err := capabilities.DropCapabilities(container); err != nil {
|
||||
if err := capabilities.DropCapabilities(container.Capabilities); err != nil {
|
||||
return fmt.Errorf("drop capabilities %s", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -5,8 +5,6 @@ import (
|
|||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/docker/libcontainer"
|
||||
)
|
||||
|
||||
// SyncPipe allows communication to and from the child processes
|
||||
|
@ -45,7 +43,7 @@ func (s *SyncPipe) Parent() *os.File {
|
|||
return s.parent
|
||||
}
|
||||
|
||||
func (s *SyncPipe) SendToChild(context libcontainer.Context) error {
|
||||
func (s *SyncPipe) SendToChild(context map[string]string) error {
|
||||
data, err := json.Marshal(context)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -54,12 +52,12 @@ func (s *SyncPipe) SendToChild(context libcontainer.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *SyncPipe) ReadFromParent() (libcontainer.Context, error) {
|
||||
func (s *SyncPipe) ReadFromParent() (map[string]string, error) {
|
||||
data, err := ioutil.ReadAll(s.child)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading from sync pipe %s", err)
|
||||
}
|
||||
var context libcontainer.Context
|
||||
var context map[string]string
|
||||
if len(data) > 0 {
|
||||
if err := json.Unmarshal(data, &context); err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
package namespaces
|
||||
|
||||
import "errors"
|
||||
|
||||
type (
|
||||
Namespace struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value int `json:"value,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
}
|
||||
Namespaces []*Namespace
|
||||
)
|
||||
|
||||
// namespaceList is used to convert the libcontainer types
|
||||
// into the names of the files located in /proc/<pid>/ns/* for
|
||||
// each namespace
|
||||
var (
|
||||
namespaceList = Namespaces{}
|
||||
ErrUnkownNamespace = errors.New("Unknown namespace")
|
||||
ErrUnsupported = errors.New("Unsupported method")
|
||||
)
|
||||
|
||||
func (ns *Namespace) String() string {
|
||||
return ns.Key
|
||||
}
|
||||
|
||||
func GetNamespace(key string) *Namespace {
|
||||
for _, ns := range namespaceList {
|
||||
if ns.Key == key {
|
||||
cpy := *ns
|
||||
return &cpy
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Contains returns true if the specified Namespace is
|
||||
// in the slice
|
||||
func (n Namespaces) Contains(ns string) bool {
|
||||
return n.Get(ns) != nil
|
||||
}
|
||||
|
||||
func (n Namespaces) Get(ns string) *Namespace {
|
||||
for _, nsp := range n {
|
||||
if nsp != nil && nsp.Key == ns {
|
||||
return nsp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package libcontainer
|
||||
package namespaces
|
||||
|
||||
import (
|
||||
"syscall"
|
|
@ -1,4 +1,4 @@
|
|||
package libcontainer
|
||||
package namespaces
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
@ -28,17 +28,3 @@ func TestNamespacesContains(t *testing.T) {
|
|||
t.Fatal("namespaces should contain NEWPID but does not")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCapabilitiesContains(t *testing.T) {
|
||||
caps := Capabilities{
|
||||
GetCapability("MKNOD"),
|
||||
GetCapability("SETPCAP"),
|
||||
}
|
||||
|
||||
if caps.Contains("SYS_ADMIN") {
|
||||
t.Fatal("capabilities should not contain SYS_ADMIN")
|
||||
}
|
||||
if !caps.Contains("MKNOD") {
|
||||
t.Fatal("capabilities should contain MKNOD but does not")
|
||||
}
|
||||
}
|
|
@ -8,19 +8,19 @@ import (
|
|||
)
|
||||
|
||||
func Exec(container *libcontainer.Container, term Terminal, rootfs, dataPath string, args []string, createCommand CreateCommand, startCallback func()) (int, error) {
|
||||
return -1, libcontainer.ErrUnsupported
|
||||
return -1, ErrUnsupported
|
||||
}
|
||||
|
||||
func Init(container *libcontainer.Container, uncleanRootfs, consolePath string, syncPipe *SyncPipe, args []string) error {
|
||||
return libcontainer.ErrUnsupported
|
||||
return ErrUnsupported
|
||||
}
|
||||
|
||||
func InitializeNetworking(container *libcontainer.Container, nspid int, pipe *SyncPipe) error {
|
||||
return libcontainer.ErrUnsupported
|
||||
return ErrUnsupported
|
||||
}
|
||||
|
||||
func SetupCgroups(container *libcontainer.Container, nspid int) (cgroups.ActiveCgroup, error) {
|
||||
return nil, libcontainer.ErrUnsupported
|
||||
return nil, ErrUnsupported
|
||||
}
|
||||
|
||||
func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
// +build linux
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/docker/libcontainer"
|
||||
)
|
||||
|
||||
// Loopback is a network strategy that provides a basic loopback device
|
||||
type Loopback struct {
|
||||
}
|
||||
|
||||
func (l *Loopback) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error {
|
||||
func (l *Loopback) Create(n *Network, nspid int, context map[string]string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *Loopback) Initialize(config *libcontainer.Network, context libcontainer.Context) error {
|
||||
func (l *Loopback) Initialize(config *Network, context map[string]string) error {
|
||||
if err := SetMtu("lo", config.Mtu); err != nil {
|
||||
return fmt.Errorf("set lo mtu to %d %s", config.Mtu, err)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// +build linux
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
|
@ -5,7 +7,6 @@ import (
|
|||
"os"
|
||||
"syscall"
|
||||
|
||||
"github.com/docker/libcontainer"
|
||||
"github.com/dotcloud/docker/pkg/system"
|
||||
)
|
||||
|
||||
|
@ -13,12 +14,12 @@ import (
|
|||
type NetNS struct {
|
||||
}
|
||||
|
||||
func (v *NetNS) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error {
|
||||
context["nspath"] = n.Context["nspath"]
|
||||
func (v *NetNS) Create(n *Network, nspid int, context map[string]string) error {
|
||||
context["nspath"] = n.NsPath
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *NetNS) Initialize(config *libcontainer.Network, context libcontainer.Context) error {
|
||||
func (v *NetNS) Initialize(config *Network, context map[string]string) error {
|
||||
nspath, exists := context["nspath"]
|
||||
if !exists {
|
||||
return fmt.Errorf("nspath does not exist in network context")
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
// +build linux
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/docker/libcontainer/netlink"
|
||||
"net"
|
||||
|
||||
"github.com/docker/libcontainer/netlink"
|
||||
)
|
||||
|
||||
func InterfaceUp(name string) error {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
// +build linux
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/docker/libcontainer"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -19,8 +19,8 @@ var strategies = map[string]NetworkStrategy{
|
|||
// NetworkStrategy represents a specific network configuration for
|
||||
// a container's networking stack
|
||||
type NetworkStrategy interface {
|
||||
Create(*libcontainer.Network, int, libcontainer.Context) error
|
||||
Initialize(*libcontainer.Network, libcontainer.Context) error
|
||||
Create(*Network, int, map[string]string) error
|
||||
Initialize(*Network, map[string]string) error
|
||||
}
|
||||
|
||||
// GetStrategy returns the specific network strategy for the
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
package network
|
||||
|
||||
// Network defines configuration for a container's networking stack
|
||||
//
|
||||
// The network configuration can be omited from a container causing the
|
||||
// container to be setup with the host's networking stack
|
||||
type Network struct {
|
||||
// Type sets the networks type, commonly veth and loopback
|
||||
Type string `json:"type,omitempty"`
|
||||
|
||||
// Path to network namespace
|
||||
NsPath string `json:"ns_path,omitempty"`
|
||||
|
||||
// The bridge to use.
|
||||
Bridge string `json:"bridge,omitempty"`
|
||||
|
||||
// Prefix for the veth interfaces.
|
||||
VethPrefix string `json:"veth_prefix,omitempty"`
|
||||
|
||||
// Address contains the IP and mask to set on the network interface
|
||||
Address string `json:"address,omitempty"`
|
||||
|
||||
// Gateway sets the gateway address that is used as the default for the interface
|
||||
Gateway string `json:"gateway,omitempty"`
|
||||
|
||||
// Mtu sets the mtu value for the interface and will be mirrored on both the host and
|
||||
// container's interfaces if a pair is created, specifically in the case of type veth
|
||||
Mtu int `json:"mtu,omitempty"`
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
// +build linux
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/docker/libcontainer"
|
||||
|
||||
"github.com/docker/libcontainer/utils"
|
||||
)
|
||||
|
||||
|
@ -14,17 +16,16 @@ type Veth struct {
|
|||
|
||||
const defaultDevice = "eth0"
|
||||
|
||||
func (v *Veth) Create(n *libcontainer.Network, nspid int, context libcontainer.Context) error {
|
||||
func (v *Veth) Create(n *Network, nspid int, context map[string]string) error {
|
||||
var (
|
||||
bridge string
|
||||
prefix string
|
||||
exists bool
|
||||
bridge = n.Bridge
|
||||
prefix = n.VethPrefix
|
||||
)
|
||||
if bridge, exists = n.Context["bridge"]; !exists {
|
||||
return fmt.Errorf("bridge does not exist in network context")
|
||||
if bridge == "" {
|
||||
return fmt.Errorf("bridge is not specified")
|
||||
}
|
||||
if prefix, exists = n.Context["prefix"]; !exists {
|
||||
return fmt.Errorf("veth prefix does not exist in network context")
|
||||
if prefix == "" {
|
||||
return fmt.Errorf("veth prefix is not specified")
|
||||
}
|
||||
name1, name2, err := createVethPair(prefix)
|
||||
if err != nil {
|
||||
|
@ -47,7 +48,7 @@ func (v *Veth) Create(n *libcontainer.Network, nspid int, context libcontainer.C
|
|||
return nil
|
||||
}
|
||||
|
||||
func (v *Veth) Initialize(config *libcontainer.Network, context libcontainer.Context) error {
|
||||
func (v *Veth) Initialize(config *Network, context map[string]string) error {
|
||||
var (
|
||||
vethChild string
|
||||
exists bool
|
||||
|
|
|
@ -121,66 +121,61 @@
|
|||
"process_label": "",
|
||||
"restrictions": "true"
|
||||
},
|
||||
"device_nodes": [
|
||||
{
|
||||
"cgroup_permissions": "rwm",
|
||||
"major_number": 10,
|
||||
"minor_number": 229,
|
||||
"path": "/dev/fuse",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"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=2d388ea3bd92",
|
||||
"HOSTNAME=koye",
|
||||
"TERM=xterm"
|
||||
],
|
||||
"hostname": "koye",
|
||||
|
@ -200,10 +195,8 @@
|
|||
},
|
||||
{
|
||||
"address": "172.17.0.101/16",
|
||||
"context": {
|
||||
"bridge": "docker0",
|
||||
"prefix": "veth"
|
||||
},
|
||||
"bridge": "docker0",
|
||||
"veth_prefix": "veth",
|
||||
"gateway": "172.17.42.1",
|
||||
"mtu": 1500,
|
||||
"type": "veth"
|
||||
|
|
|
@ -121,55 +121,57 @@
|
|||
"process_label": "",
|
||||
"restrictions": "true"
|
||||
},
|
||||
"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
|
||||
}
|
||||
],
|
||||
"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",
|
||||
|
|
|
@ -3,7 +3,6 @@ package capabilities
|
|||
import (
|
||||
"os"
|
||||
|
||||
"github.com/docker/libcontainer"
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
)
|
||||
|
||||
|
@ -11,13 +10,13 @@ const allCapabilityTypes = capability.CAPS | capability.BOUNDS
|
|||
|
||||
// DropBoundingSet drops the capability bounding set to those specified in the
|
||||
// container configuration.
|
||||
func DropBoundingSet(container *libcontainer.Container) error {
|
||||
func DropBoundingSet(capabilities []string) error {
|
||||
c, err := capability.NewPid(os.Getpid())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keep := getEnabledCapabilities(container)
|
||||
keep := getEnabledCapabilities(capabilities)
|
||||
c.Clear(capability.BOUNDS)
|
||||
c.Set(capability.BOUNDS, keep...)
|
||||
|
||||
|
@ -29,13 +28,13 @@ func DropBoundingSet(container *libcontainer.Container) error {
|
|||
}
|
||||
|
||||
// DropCapabilities drops all capabilities for the current process expect those specified in the container configuration.
|
||||
func DropCapabilities(container *libcontainer.Container) error {
|
||||
func DropCapabilities(capList []string) error {
|
||||
c, err := capability.NewPid(os.Getpid())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keep := getEnabledCapabilities(container)
|
||||
keep := getEnabledCapabilities(capList)
|
||||
c.Clear(allCapabilityTypes)
|
||||
c.Set(allCapabilityTypes, keep...)
|
||||
|
||||
|
@ -46,10 +45,10 @@ func DropCapabilities(container *libcontainer.Container) error {
|
|||
}
|
||||
|
||||
// getEnabledCapabilities returns the capabilities that should not be dropped by the container.
|
||||
func getEnabledCapabilities(container *libcontainer.Container) []capability.Cap {
|
||||
func getEnabledCapabilities(capList []string) []capability.Cap {
|
||||
keep := []capability.Cap{}
|
||||
for _, capability := range container.Capabilities {
|
||||
if c := libcontainer.GetCapability(capability); c != nil {
|
||||
for _, capability := range capList {
|
||||
if c := GetCapability(capability); c != nil {
|
||||
keep = append(keep, c.Value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
package capabilities
|
||||
|
||||
import "github.com/syndtr/gocapability/capability"
|
||||
|
||||
type (
|
||||
CapabilityMapping struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value capability.Cap `json:"value,omitempty"`
|
||||
}
|
||||
Capabilities []*CapabilityMapping
|
||||
)
|
||||
|
||||
func (c *CapabilityMapping) String() string {
|
||||
return c.Key
|
||||
}
|
||||
|
||||
func GetCapability(key string) *CapabilityMapping {
|
||||
for _, capp := range capabilityList {
|
||||
if capp.Key == key {
|
||||
cpy := *capp
|
||||
return &cpy
|
||||
}
|
||||
}
|
||||
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 {
|
||||
return c.get(capp) != nil
|
||||
}
|
||||
|
||||
func (c Capabilities) get(capp string) *CapabilityMapping {
|
||||
for _, cap := range c {
|
||||
if cap.Key == capp {
|
||||
return cap
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var capabilityList = Capabilities{
|
||||
{Key: "SETPCAP", Value: capability.CAP_SETPCAP},
|
||||
{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE},
|
||||
{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO},
|
||||
{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT},
|
||||
{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN},
|
||||
{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE},
|
||||
{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE},
|
||||
{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME},
|
||||
{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG},
|
||||
{Key: "MKNOD", Value: capability.CAP_MKNOD},
|
||||
{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE},
|
||||
{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL},
|
||||
{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE},
|
||||
{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN},
|
||||
{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN},
|
||||
{Key: "SYSLOG", Value: capability.CAP_SYSLOG},
|
||||
{Key: "SETUID", Value: capability.CAP_SETUID},
|
||||
{Key: "SETGID", Value: capability.CAP_SETGID},
|
||||
{Key: "CHOWN", Value: capability.CAP_CHOWN},
|
||||
{Key: "NET_RAW", Value: capability.CAP_NET_RAW},
|
||||
{Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE},
|
||||
{Key: "FOWNER", Value: capability.CAP_FOWNER},
|
||||
{Key: "DAC_READ_SEARCH", Value: capability.CAP_DAC_READ_SEARCH},
|
||||
{Key: "FSETID", Value: capability.CAP_FSETID},
|
||||
{Key: "KILL", Value: capability.CAP_KILL},
|
||||
{Key: "SETGID", Value: capability.CAP_SETGID},
|
||||
{Key: "SETUID", Value: capability.CAP_SETUID},
|
||||
{Key: "LINUX_IMMUTABLE", Value: capability.CAP_LINUX_IMMUTABLE},
|
||||
{Key: "NET_BIND_SERVICE", Value: capability.CAP_NET_BIND_SERVICE},
|
||||
{Key: "NET_BROADCAST", Value: capability.CAP_NET_BROADCAST},
|
||||
{Key: "IPC_LOCK", Value: capability.CAP_IPC_LOCK},
|
||||
{Key: "IPC_OWNER", Value: capability.CAP_IPC_OWNER},
|
||||
{Key: "SYS_CHROOT", Value: capability.CAP_SYS_CHROOT},
|
||||
{Key: "SYS_PTRACE", Value: capability.CAP_SYS_PTRACE},
|
||||
{Key: "SYS_BOOT", Value: capability.CAP_SYS_BOOT},
|
||||
{Key: "LEASE", Value: capability.CAP_LEASE},
|
||||
{Key: "SETFCAP", Value: capability.CAP_SETFCAP},
|
||||
{Key: "WAKE_ALARM", Value: capability.CAP_WAKE_ALARM},
|
||||
{Key: "BLOCK_SUSPEND", Value: capability.CAP_BLOCK_SUSPEND},
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package capabilities
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCapabilitiesContains(t *testing.T) {
|
||||
caps := Capabilities{
|
||||
GetCapability("MKNOD"),
|
||||
GetCapability("SETPCAP"),
|
||||
}
|
||||
|
||||
if caps.contains("SYS_ADMIN") {
|
||||
t.Fatal("capabilities should not contain SYS_ADMIN")
|
||||
}
|
||||
if !caps.contains("MKNOD") {
|
||||
t.Fatal("capabilities should contain MKNOD but does not")
|
||||
}
|
||||
}
|
165
types.go
165
types.go
|
@ -1,165 +0,0 @@
|
|||
package libcontainer
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/syndtr/gocapability/capability"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrUnkownNamespace = errors.New("Unknown namespace")
|
||||
ErrUnkownCapability = errors.New("Unknown capability")
|
||||
ErrUnsupported = errors.New("Unsupported method")
|
||||
)
|
||||
|
||||
type Mounts []Mount
|
||||
|
||||
func (s Mounts) OfType(t string) Mounts {
|
||||
out := Mounts{}
|
||||
for _, m := range s {
|
||||
if m.Type == t {
|
||||
out = append(out, m)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Source string `json:"source,omitempty"` // Source path, in the host namespace
|
||||
Destination string `json:"destination,omitempty"` // Destination path, in the container
|
||||
Writable bool `json:"writable,omitempty"`
|
||||
Private bool `json:"private,omitempty"`
|
||||
}
|
||||
|
||||
// namespaceList is used to convert the libcontainer types
|
||||
// into the names of the files located in /proc/<pid>/ns/* for
|
||||
// each namespace
|
||||
var (
|
||||
namespaceList = Namespaces{}
|
||||
|
||||
capabilityList = Capabilities{
|
||||
{Key: "SETPCAP", Value: capability.CAP_SETPCAP},
|
||||
{Key: "SYS_MODULE", Value: capability.CAP_SYS_MODULE},
|
||||
{Key: "SYS_RAWIO", Value: capability.CAP_SYS_RAWIO},
|
||||
{Key: "SYS_PACCT", Value: capability.CAP_SYS_PACCT},
|
||||
{Key: "SYS_ADMIN", Value: capability.CAP_SYS_ADMIN},
|
||||
{Key: "SYS_NICE", Value: capability.CAP_SYS_NICE},
|
||||
{Key: "SYS_RESOURCE", Value: capability.CAP_SYS_RESOURCE},
|
||||
{Key: "SYS_TIME", Value: capability.CAP_SYS_TIME},
|
||||
{Key: "SYS_TTY_CONFIG", Value: capability.CAP_SYS_TTY_CONFIG},
|
||||
{Key: "MKNOD", Value: capability.CAP_MKNOD},
|
||||
{Key: "AUDIT_WRITE", Value: capability.CAP_AUDIT_WRITE},
|
||||
{Key: "AUDIT_CONTROL", Value: capability.CAP_AUDIT_CONTROL},
|
||||
{Key: "MAC_OVERRIDE", Value: capability.CAP_MAC_OVERRIDE},
|
||||
{Key: "MAC_ADMIN", Value: capability.CAP_MAC_ADMIN},
|
||||
{Key: "NET_ADMIN", Value: capability.CAP_NET_ADMIN},
|
||||
{Key: "SYSLOG", Value: capability.CAP_SYSLOG},
|
||||
{Key: "SETUID", Value: capability.CAP_SETUID},
|
||||
{Key: "SETGID", Value: capability.CAP_SETGID},
|
||||
{Key: "CHOWN", Value: capability.CAP_CHOWN},
|
||||
{Key: "NET_RAW", Value: capability.CAP_NET_RAW},
|
||||
{Key: "DAC_OVERRIDE", Value: capability.CAP_DAC_OVERRIDE},
|
||||
{Key: "FOWNER", Value: capability.CAP_FOWNER},
|
||||
{Key: "DAC_READ_SEARCH", Value: capability.CAP_DAC_READ_SEARCH},
|
||||
{Key: "FSETID", Value: capability.CAP_FSETID},
|
||||
{Key: "KILL", Value: capability.CAP_KILL},
|
||||
{Key: "SETGID", Value: capability.CAP_SETGID},
|
||||
{Key: "SETUID", Value: capability.CAP_SETUID},
|
||||
{Key: "LINUX_IMMUTABLE", Value: capability.CAP_LINUX_IMMUTABLE},
|
||||
{Key: "NET_BIND_SERVICE", Value: capability.CAP_NET_BIND_SERVICE},
|
||||
{Key: "NET_BROADCAST", Value: capability.CAP_NET_BROADCAST},
|
||||
{Key: "IPC_LOCK", Value: capability.CAP_IPC_LOCK},
|
||||
{Key: "IPC_OWNER", Value: capability.CAP_IPC_OWNER},
|
||||
{Key: "SYS_CHROOT", Value: capability.CAP_SYS_CHROOT},
|
||||
{Key: "SYS_PTRACE", Value: capability.CAP_SYS_PTRACE},
|
||||
{Key: "SYS_BOOT", Value: capability.CAP_SYS_BOOT},
|
||||
{Key: "LEASE", Value: capability.CAP_LEASE},
|
||||
{Key: "SETFCAP", Value: capability.CAP_SETFCAP},
|
||||
{Key: "WAKE_ALARM", Value: capability.CAP_WAKE_ALARM},
|
||||
{Key: "BLOCK_SUSPEND", Value: capability.CAP_BLOCK_SUSPEND},
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
Namespace struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value int `json:"value,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
}
|
||||
Namespaces []*Namespace
|
||||
)
|
||||
|
||||
func (ns *Namespace) String() string {
|
||||
return ns.Key
|
||||
}
|
||||
|
||||
func GetNamespace(key string) *Namespace {
|
||||
for _, ns := range namespaceList {
|
||||
if ns.Key == key {
|
||||
cpy := *ns
|
||||
return &cpy
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Contains returns true if the specified Namespace is
|
||||
// in the slice
|
||||
func (n Namespaces) Contains(ns string) bool {
|
||||
return n.Get(ns) != nil
|
||||
}
|
||||
|
||||
func (n Namespaces) Get(ns string) *Namespace {
|
||||
for _, nsp := range n {
|
||||
if nsp != nil && nsp.Key == ns {
|
||||
return nsp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type (
|
||||
Capability struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value capability.Cap `json:"value,omitempty"`
|
||||
}
|
||||
Capabilities []*Capability
|
||||
)
|
||||
|
||||
func (c *Capability) String() string {
|
||||
return c.Key
|
||||
}
|
||||
|
||||
func GetCapability(key string) *Capability {
|
||||
for _, capp := range capabilityList {
|
||||
if capp.Key == key {
|
||||
cpy := *capp
|
||||
return &cpy
|
||||
}
|
||||
}
|
||||
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 {
|
||||
return c.Get(capp) != nil
|
||||
}
|
||||
|
||||
func (c Capabilities) Get(capp string) *Capability {
|
||||
for _, cap := range c {
|
||||
if cap.Key == capp {
|
||||
return cap
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue