Jelajahi Sumber

LXC CAP ADD CAP DROP IN TEMPLATE

Added cap-drop and cap-add in lxc template
Docker-DCO-1.1-Signed-off-by: Abin Shahab <ashahab@altiscale.com> (github: ashahab-altiscale)
Abin Shahab 10 tahun lalu
induk
melakukan
fdf7457683

+ 0 - 8
daemon/execdriver/lxc/driver.go

@@ -123,14 +123,6 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
 		params = append(params, "-w", c.WorkingDir)
 	}
 
-	if len(c.CapAdd) > 0 {
-		params = append(params, fmt.Sprintf("-cap-add=%s", strings.Join(c.CapAdd, ":")))
-	}
-
-	if len(c.CapDrop) > 0 {
-		params = append(params, fmt.Sprintf("-cap-drop=%s", strings.Join(c.CapDrop, ":")))
-	}
-
 	params = append(params, "--", c.ProcessConfig.Entrypoint)
 	params = append(params, c.ProcessConfig.Arguments...)
 

+ 1 - 61
daemon/execdriver/lxc/init.go

@@ -6,7 +6,6 @@ import (
 	"fmt"
 	"io/ioutil"
 	"log"
-	"net"
 	"os"
 	"os/exec"
 	"runtime"
@@ -14,7 +13,6 @@ import (
 	"syscall"
 
 	"github.com/docker/docker/pkg/reexec"
-	"github.com/docker/libcontainer/netlink"
 )
 
 // Args provided to the init function for a driver
@@ -59,12 +57,7 @@ func setupNamespace(args *InitArgs) error {
 	if err := setupEnv(args); err != nil {
 		return err
 	}
-	if err := setupHostname(args); err != nil {
-		return err
-	}
-	if err := setupNetworking(args); err != nil {
-		return err
-	}
+
 	if err := finalizeNamespace(args); err != nil {
 		return err
 	}
@@ -138,59 +131,6 @@ func setupEnv(args *InitArgs) error {
 	return nil
 }
 
-func setupHostname(args *InitArgs) error {
-	hostname := getEnv(args, "HOSTNAME")
-	if hostname == "" {
-		return nil
-	}
-	return setHostname(hostname)
-}
-
-// Setup networking
-func setupNetworking(args *InitArgs) error {
-	if args.Ip != "" {
-		// eth0
-		iface, err := net.InterfaceByName("eth0")
-		if err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		ip, ipNet, err := net.ParseCIDR(args.Ip)
-		if err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		if err := netlink.NetworkLinkAddIp(iface, ip, ipNet); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		if err := netlink.NetworkSetMTU(iface, args.Mtu); err != nil {
-			return fmt.Errorf("Unable to set MTU: %v", err)
-		}
-		if err := netlink.NetworkLinkUp(iface); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-
-		// loopback
-		iface, err = net.InterfaceByName("lo")
-		if err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-		if err := netlink.NetworkLinkUp(iface); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-	}
-	if args.Gateway != "" {
-		gw := net.ParseIP(args.Gateway)
-		if gw == nil {
-			return fmt.Errorf("Unable to set up networking, %s is not a valid gateway IP", args.Gateway)
-		}
-
-		if err := netlink.AddDefaultGw(gw.String(), "eth0"); err != nil {
-			return fmt.Errorf("Unable to set up networking: %v", err)
-		}
-	}
-
-	return nil
-}
-
 // Setup working directory
 func setupWorkingDirectory(args *InitArgs) error {
 	if args.WorkDir == "" {

+ 0 - 55
daemon/execdriver/lxc/lxc_init_linux.go

@@ -2,74 +2,19 @@ package lxc
 
 import (
 	"fmt"
-	"strings"
-	"syscall"
-
-	"github.com/docker/docker/daemon/execdriver"
-	"github.com/docker/docker/daemon/execdriver/native/template"
 	"github.com/docker/libcontainer/namespaces"
-	"github.com/docker/libcontainer/security/capabilities"
-	"github.com/docker/libcontainer/system"
 	"github.com/docker/libcontainer/utils"
 )
 
-func setHostname(hostname string) error {
-	return syscall.Sethostname([]byte(hostname))
-}
-
 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
 	}

+ 0 - 4
daemon/execdriver/lxc/lxc_init_unsupported.go

@@ -2,10 +2,6 @@
 
 package lxc
 
-func setHostname(hostname string) error {
-	panic("Not supported on darwin")
-}
-
 func finalizeNamespace(args *InitArgs) error {
 	panic("Not supported on darwin")
 }

+ 45 - 0
daemon/execdriver/lxc/lxc_template.go

@@ -2,6 +2,7 @@ package lxc
 
 import (
 	"github.com/docker/docker/daemon/execdriver"
+	nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template"
 	"github.com/docker/libcontainer/label"
 	"os"
 	"strings"
@@ -15,6 +16,13 @@ lxc.network.type = veth
 lxc.network.link = {{.Network.Interface.Bridge}}
 lxc.network.name = eth0
 lxc.network.mtu = {{.Network.Mtu}}
+{{if .Network.Interface.IPAddress}}
+lxc.network.ipv4 = {{.Network.Interface.IPAddress}}/{{.Network.Interface.IPPrefixLen}}
+{{end}}
+{{if .Network.Interface.Gateway}}
+lxc.network.ipv4.gateway = {{.Network.Interface.Gateway}}
+{{end}}
+lxc.network.flags = up
 {{else if .Network.HostNetworking}}
 lxc.network.type = none
 {{else}}
@@ -78,6 +86,18 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
 {{end}}
 {{end}}
 
+{{if .ProcessConfig.Env}}
+lxc.utsname = {{getHostname .ProcessConfig.Env}}
+{{end}}
+
+{{if .ProcessConfig.Privileged}}
+# No cap values are needed, as lxc is starting in privileged mode
+{{else}}
+{{range $value := keepCapabilities .CapAdd .CapDrop}}
+lxc.cap.keep = {{$value}}
+{{end}}
+{{end}}
+
 {{if .ProcessConfig.Privileged}}
 {{if .AppArmor}}
 lxc.aa_profile = unconfined
@@ -118,6 +138,19 @@ func escapeFstabSpaces(field string) string {
 	return strings.Replace(field, " ", "\\040", -1)
 }
 
+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 isDirectory(source string) string {
 	f, err := os.Stat(source)
 	if err != nil {
@@ -152,6 +185,16 @@ func getLabel(c map[string][]string, name string) string {
 	return ""
 }
 
+func getHostname(env []string) string {
+	for _, kv := range env {
+		parts := strings.SplitN(kv, "=", 2)
+		if parts[0] == "HOSTNAME" && len(parts) == 2 {
+			return parts[1]
+		}
+	}
+	return ""
+}
+
 func init() {
 	var err error
 	funcMap := template.FuncMap{
@@ -159,6 +202,8 @@ func init() {
 		"escapeFstabSpaces": escapeFstabSpaces,
 		"formatMountLabel":  label.FormatMountLabel,
 		"isDirectory":       isDirectory,
+		"keepCapabilities":  keepCapabilities,
+		"getHostname":       getHostname,
 	}
 	LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
 	if err != nil {

+ 72 - 0
daemon/execdriver/lxc/lxc_template_unit_test.go

@@ -14,6 +14,7 @@ import (
 	"time"
 
 	"github.com/docker/docker/daemon/execdriver"
+	nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template"
 	"github.com/docker/libcontainer/devices"
 )
 
@@ -104,6 +105,10 @@ func TestCustomLxcConfig(t *testing.T) {
 }
 
 func grepFile(t *testing.T, path string, pattern string) {
+	grepFileWithReverse(t, path, pattern, false)
+}
+
+func grepFileWithReverse(t *testing.T, path string, pattern string, inverseGrep bool) {
 	f, err := os.Open(path)
 	if err != nil {
 		t.Fatal(err)
@@ -117,9 +122,15 @@ func grepFile(t *testing.T, path string, pattern string) {
 	for err == nil {
 		line, err = r.ReadString('\n')
 		if strings.Contains(line, pattern) == true {
+			if inverseGrep {
+				t.Fatalf("grepFile: pattern \"%s\" found in \"%s\"", pattern, path)
+			}
 			return
 		}
 	}
+	if inverseGrep {
+		return
+	}
 	t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
 }
 
@@ -228,3 +239,64 @@ func TestCustomLxcConfigMounts(t *testing.T) {
 	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,ro,create=%s 0 0", tempDir, "/"+tempDir, "dir"))
 	grepFile(t, p, fmt.Sprintf("lxc.mount.entry = %s %s none rbind,rw,create=%s 0 0", tempFile.Name(), "/"+tempFile.Name(), "file"))
 }
+
+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)
+}