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 }
// 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.Env) container.Tty = c.Tty container.User = c.User container.WorkingDir = c.WorkingDir container.Env = c.Env container.Cgroups.Name = c.ID container.Cgroups.AllowedDevices = c.AllowedDevices container.MountConfig.DeviceNodes = c.AutoCreatedDevices // 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.createNetwork(container, c); err != nil { return nil, err } if c.Privileged { if err := d.setPrivileged(container); err != nil { return nil, err } } else { if err := d.setCapabilities(container, c); err != nil { return nil, err } } 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() if err := configuration.ParseConfiguration(container, cmds, c.Config["native"]); err != nil { return nil, err } return container, 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 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 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 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") } }