func TestCustomLxcConfigMisc(t *testing.T) { root, err := ioutil.TempDir("", "TestCustomLxcConfig") if err != nil { t.Fatal(err) } defer os.RemoveAll(root) os.MkdirAll(path.Join(root, "containers", "1"), 0777) driver, err := NewDriver(root, "", false) if err != nil { t.Fatal(err) } processConfig := execdriver.ProcessConfig{ Privileged: false, } processConfig.Env = []string{"HOSTNAME=testhost"} command := &execdriver.Command{ ID: "1", LxcConfig: []string{ "lxc.cgroup.cpuset.cpus = 0,1", }, Network: &execdriver.Network{ Mtu: 1500, Interface: &execdriver.NetworkInterface{ Gateway: "10.10.10.1", IPAddress: "10.10.10.10", IPPrefixLen: 24, Bridge: "docker0", }, }, ProcessConfig: processConfig, CapAdd: []string{"net_admin", "syslog"}, CapDrop: []string{"kill", "mknod"}, } p, err := driver.generateLXCConfig(command) if err != nil { t.Fatal(err) } // network grepFile(t, p, "lxc.network.type = veth") grepFile(t, p, "lxc.network.link = docker0") grepFile(t, p, "lxc.network.name = eth0") grepFile(t, p, "lxc.network.ipv4 = 10.10.10.10/24") grepFile(t, p, "lxc.network.ipv4.gateway = 10.10.10.1") grepFile(t, p, "lxc.network.flags = up") // hostname grepFile(t, p, "lxc.utsname = testhost") grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") container := nativeTemplate.New() for _, cap := range container.Capabilities { cap = strings.ToLower(cap) if cap != "mknod" && cap != "kill" { grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", cap)) } } grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = kill"), true) grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = mknod"), true) }
// createContainer populates and configures the container type with the // data provided by the execdriver.Command func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, error) { container := template.New() container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env) container.Tty = c.ProcessConfig.Tty container.User = c.ProcessConfig.User container.WorkingDir = c.WorkingDir container.Env = c.ProcessConfig.Env container.Cgroups.Name = c.ID container.Cgroups.AllowedDevices = c.AllowedDevices container.MountConfig.DeviceNodes = c.AutoCreatedDevices container.RootFs = c.Rootfs // check to see if we are running in ramdisk to disable pivot root container.MountConfig.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != "" container.RestrictSys = true if err := d.createIpc(container, c); err != nil { return nil, err } if err := d.createNetwork(container, c); err != nil { return nil, err } if c.ProcessConfig.Privileged { if err := d.setPrivileged(container); err != nil { return nil, err } } else { if err := d.setCapabilities(container, c); err != nil { return nil, err } } if c.AppArmorProfile != "" { container.AppArmorProfile = c.AppArmorProfile } if err := d.setupCgroups(container, c); err != nil { return nil, err } if err := d.setupMounts(container, c); err != nil { return nil, err } if err := d.setupLabels(container, c); err != nil { return nil, err } cmds := make(map[string]*exec.Cmd) d.Lock() for k, v := range d.activeContainers { cmds[k] = v.cmd } d.Unlock() return container, nil }
func main() { defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"} cli, err := client.NewClient(dockerHost, "", nil, defaultHeaders) if err != nil { panic(err) } // get container info c, err := cli.ContainerInspect(context.Background(), arg) if err != nil { logrus.Fatalf("inspecting container (%s) failed: %v", arg, err) } t := native.New() spec, err := parse.Config(c, platform.OSType, platform.Architecture, t.Capabilities, idroot, idlen) if err != nil { logrus.Fatalf("Spec config conversion for %s failed: %v", arg, err) } // fill in hooks, if passed through command line spec.Hooks = hooks if err := writeConfig(spec); err != nil { logrus.Fatal(err) } fmt.Printf("%s has been saved.\n", specConfig) }
func finalizeNamespace(args *InitArgs) error { if err := utils.CloseExecFrom(3); err != nil { return err } // We use the native drivers default template so that things like caps are consistent // across both drivers container := template.New() if !args.Privileged { // drop capabilities in bounding set before changing user if err := capabilities.DropBoundingSet(container.Capabilities); err != nil { return fmt.Errorf("drop bounding set %s", err) } // preserve existing capabilities while we change users if err := system.SetKeepCaps(); err != nil { return fmt.Errorf("set keep caps %s", err) } } if err := namespaces.SetupUser(args.User); err != nil { return fmt.Errorf("setup user %s", err) } if !args.Privileged { if err := system.ClearKeepCaps(); err != nil { return fmt.Errorf("clear keep caps %s", err) } var ( adds []string drops []string ) if args.CapAdd != "" { adds = strings.Split(args.CapAdd, ":") } if args.CapDrop != "" { drops = strings.Split(args.CapDrop, ":") } caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) if err != nil { return err } // drop all other capabilities if err := capabilities.DropCapabilities(caps); err != nil { return fmt.Errorf("drop capabilities %s", err) } } if err := setupWorkingDirectory(args); err != nil { return err } return nil }
func TestConfigurationsDoNotConflict(t *testing.T) { var ( container1 = template.New() container2 = template.New() opts = []string{ "cap.add=NET_ADMIN", } ) if err := ParseConfiguration(container1, nil, opts); err != nil { t.Fatal(err) } if !hasCapability("NET_ADMIN", container1.Capabilities) { t.Fatal("container one should have NET_ADMIN enabled") } if hasCapability("NET_ADMIN", container2.Capabilities) { t.Fatal("container two should not have NET_ADMIN enabled") } }
func keepCapabilities(adds []string, drops []string) []string { container := nativeTemplate.New() caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) var newCaps []string for _, cap := range caps { newCaps = append(newCaps, strings.ToLower(cap)) } if err != nil { return []string{} } return newCaps }
func TestCustomLxcConfigMisc(t *testing.T) { root, err := ioutil.TempDir("", "TestCustomLxcConfig") if err != nil { t.Fatal(err) } defer os.RemoveAll(root) os.MkdirAll(path.Join(root, "containers", "1"), 0777) driver, err := NewDriver(root, root, "", true) if err != nil { t.Fatal(err) } processConfig := execdriver.ProcessConfig{ Privileged: false, } processConfig.Env = []string{"HOSTNAME=testhost"} command := &execdriver.Command{ CommonCommand: execdriver.CommonCommand{ ID: "1", Network: &execdriver.Network{ Mtu: 1500, }, ProcessConfig: processConfig, }, LxcConfig: []string{ "lxc.cgroup.cpuset.cpus = 0,1", }, CapAdd: []string{"net_admin", "syslog"}, CapDrop: []string{"kill", "mknod"}, AppArmorProfile: "lxc-container-default-with-nesting", } p, err := driver.generateLXCConfig(command) if err != nil { t.Fatal(err) } grepFile(t, p, "lxc.aa_profile = lxc-container-default-with-nesting") // hostname grepFile(t, p, "lxc.utsname = testhost") grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") container := nativeTemplate.New() for _, cap := range container.Capabilities { realCap := execdriver.GetCapability(cap) numCap := fmt.Sprintf("%d", realCap.Value) if cap != "MKNOD" && cap != "KILL" { grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) } } grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) }
func TestCustomLxcConfigMiscOverride(t *testing.T) { root, err := ioutil.TempDir("", "TestCustomLxcConfig") if err != nil { t.Fatal(err) } defer os.RemoveAll(root) os.MkdirAll(path.Join(root, "containers", "1"), 0777) driver, err := NewDriver(root, root, "", false) if err != nil { t.Fatal(err) } processConfig := execdriver.ProcessConfig{ Privileged: false, } processConfig.Env = []string{"HOSTNAME=testhost"} command := &execdriver.Command{ ID: "1", LxcConfig: []string{ "lxc.cgroup.cpuset.cpus = 0,1", "lxc.network.ipv4 = 172.0.0.1", }, Network: &execdriver.Network{ Mtu: 1500, Interface: nil, }, ProcessConfig: processConfig, CapAdd: []string{"NET_ADMIN", "SYSLOG"}, CapDrop: []string{"KILL", "MKNOD"}, } p, err := driver.generateLXCConfig(command) if err != nil { t.Fatal(err) } // hostname grepFile(t, p, "lxc.utsname = testhost") grepFile(t, p, "lxc.cgroup.cpuset.cpus = 0,1") container := nativeTemplate.New() for _, cap := range container.Capabilities { realCap := execdriver.GetCapability(cap) numCap := fmt.Sprintf("%d", realCap.Value) if cap != "MKNOD" && cap != "KILL" { grepFile(t, p, fmt.Sprintf("lxc.cap.keep = %s", numCap)) } } grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_KILL), true) grepFileWithReverse(t, p, fmt.Sprintf("lxc.cap.keep = %d", capability.CAP_MKNOD), true) }
func TestCpuShares(t *testing.T) { var ( container = template.New() opts = []string{ "cgroups.cpu_shares=1048", } ) if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if expected := int64(1048); container.Cgroups.CpuShares != expected { t.Fatalf("expected cpu shares %d got %d", expected, container.Cgroups.CpuShares) } }
func TestAppArmorProfile(t *testing.T) { var ( container = template.New() opts = []string{ "apparmor_profile=koye-the-protector", } ) if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if expected := "koye-the-protector"; container.AppArmorProfile != expected { t.Fatalf("expected profile %s got %s", expected, container.AppArmorProfile) } }
func TestCpusetCpus(t *testing.T) { var ( container = template.New() opts = []string{ "cgroups.cpuset.cpus=1,2", } ) if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if expected := "1,2"; container.Cgroups.CpusetCpus != expected { t.Fatalf("expected %s got %s for cpuset.cpus", expected, container.Cgroups.CpusetCpus) } }
func TestDropNamespace(t *testing.T) { var ( container = template.New() opts = []string{ "ns.drop=NEWNET", } ) if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if container.Namespaces["NEWNET"] { t.Fatal("container should not have NEWNET enabled") } }
func TestMemoryReservation(t *testing.T) { var ( container = template.New() opts = []string{ "cgroups.memory_reservation=500m", } ) if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if expected := int64(500 * 1024 * 1024); container.Cgroups.MemoryReservation != expected { t.Fatalf("expected memory reservation %d got %d", expected, container.Cgroups.MemoryReservation) } }
func TestDropCap(t *testing.T) { var ( container = template.New() opts = []string{ "cap.drop=MKNOD", } ) // enabled all caps like in privileged mode container.Capabilities = capabilities.GetAllCapabilities() if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if hasCapability("MKNOD", container.Capabilities) { t.Fatal("container should not have MKNOD enabled") } }
func keepCapabilities(adds []string, drops []string) ([]string, error) { container := nativeTemplate.New() logrus.Debugf("adds %s drops %s\n", adds, drops) caps, err := execdriver.TweakCapabilities(container.Capabilities, adds, drops) if err != nil { return nil, err } var newCaps []string for _, cap := range caps { logrus.Debugf("cap %s\n", cap) realCap := execdriver.GetCapability(cap) numCap := fmt.Sprintf("%d", realCap.Value) newCaps = append(newCaps, numCap) } return newCaps, nil }
// InitContainer is the initialization of a container config. // It returns the initial configs for a container. It's mostly // defined by the default template. func InitContainer(c *Command) *configs.Config { container := template.New() container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env) container.Cgroups.Name = c.ID container.Cgroups.Resources.AllowedDevices = c.AllowedDevices container.Devices = filterDevices(c.AutoCreatedDevices, (c.RemappedRoot.UID != 0)) container.Rootfs = c.Rootfs container.Readonlyfs = c.ReadonlyRootfs // This can be overridden later by driver during mount setup based // on volume options SetRootPropagation(container, mount.RPRIVATE) container.Cgroups.Parent = c.CgroupParent // check to see if we are running in ramdisk to disable pivot root container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != "" return container }
func InitContainer(c *Command) *libcontainer.Config { container := template.New() container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env) container.Tty = c.ProcessConfig.Tty container.User = c.ProcessConfig.User container.WorkingDir = c.WorkingDir container.Env = c.ProcessConfig.Env container.Cgroups.Name = c.ID container.Cgroups.AllowedDevices = c.AllowedDevices container.MountConfig.DeviceNodes = c.AutoCreatedDevices container.RootFs = c.Rootfs container.MountConfig.ReadonlyFs = c.ReadonlyRootfs // check to see if we are running in ramdisk to disable pivot root container.MountConfig.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != "" container.RestrictSys = true return container }
func TestAddCap(t *testing.T) { var ( container = template.New() opts = []string{ "cap.add=MKNOD", "cap.add=SYS_ADMIN", } ) if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if !hasCapability("MKNOD", container.Capabilities) { t.Fatal("container should have MKNOD enabled") } if !hasCapability("SYS_ADMIN", container.Capabilities) { t.Fatal("container should have SYS_ADMIN enabled") } }
func TestSetReadonlyRootFs(t *testing.T) { var ( container = template.New() opts = []string{ "fs.readonly=true", } ) if container.MountConfig.ReadonlyFs { t.Fatal("container should not have a readonly rootfs by default") } if err := ParseConfiguration(container, nil, opts); err != nil { t.Fatal(err) } if !container.MountConfig.ReadonlyFs { t.Fatal("container should have a readonly rootfs") } }
func InitContainer(c *Command) *configs.Config { container := template.New() container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env) container.Cgroups.Name = c.ID container.Cgroups.AllowedDevices = c.AllowedDevices container.Devices = c.AutoCreatedDevices container.Rootfs = c.Rootfs container.Readonlyfs = c.ReadonlyRootfs // check to see if we are running in ramdisk to disable pivot root container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != "" // Default parent cgroup is "docker". Override if required. if c.CgroupParent != "" { container.Cgroups.Parent = c.CgroupParent } return container }
// InitContainer is the initialization of a container config. // It returns the initial configs for a container. It's mostly // defined by the default template. func InitContainer(c *Command) *configs.Config { container := template.New() container.Hostname = getEnv("HOSTNAME", c.ProcessConfig.Env) container.Cgroups.Name = c.ID container.Cgroups.AllowedDevices = c.AllowedDevices container.Devices = c.AutoCreatedDevices container.Rootfs = c.Rootfs container.Readonlyfs = c.ReadonlyRootfs // This can be overridden later by driver during mount setup based // on volume options SetRootPropagation(container, mount.RPRIVATE) // check to see if we are running in ramdisk to disable pivot root container.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != "" // Default parent cgroup is "docker". Override if required. if c.CgroupParent != "" { container.Cgroups.Parent = c.CgroupParent } return container }
func main() { defaultHeaders := map[string]string{"User-Agent": "engine-api-cli-1.0"} cli, err := client.NewClient(dockerHost, "", nil, defaultHeaders) if err != nil { panic(err) } // get container info c, err := cli.ContainerInspect(arg) if err != nil { logrus.Fatalf("inspecting container (%s) failed: %v", arg, err) } // get daemon info info, err := cli.Info() if err != nil { logrus.Fatalf("getting daemon info failed: %v", err) } t := native.New() spec, err := parse.Config(c, info, t.Capabilities) if err != nil { logrus.Fatalf("Spec config conversion for %s failed: %v", arg, err) } rspec, err := parse.RuntimeConfig(c) if err != nil { logrus.Fatalf("Spec runtime config conversion for %s failed: %v", arg, err) } // fill in hooks, if passed through command line rspec.Hooks = hooks if err := writeConfigs(spec, rspec); err != nil { logrus.Fatal(err) } fmt.Printf("%s and %s have been saved.", specConfig, runtimeConfig) }