зеркало из https://github.com/microsoft/docker.git
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)
This commit is contained in:
Родитель
595cd5279e
Коммит
fdf7457683
|
@ -123,14 +123,6 @@ func (d *driver) Run(c *execdriver.Command, pipes *execdriver.Pipes, startCallba
|
||||||
params = append(params, "-w", c.WorkingDir)
|
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.Entrypoint)
|
||||||
params = append(params, c.ProcessConfig.Arguments...)
|
params = append(params, c.ProcessConfig.Arguments...)
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -14,7 +13,6 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/docker/docker/pkg/reexec"
|
"github.com/docker/docker/pkg/reexec"
|
||||||
"github.com/docker/libcontainer/netlink"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Args provided to the init function for a driver
|
// Args provided to the init function for a driver
|
||||||
|
@ -59,12 +57,7 @@ func setupNamespace(args *InitArgs) error {
|
||||||
if err := setupEnv(args); err != nil {
|
if err := setupEnv(args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := setupHostname(args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := setupNetworking(args); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := finalizeNamespace(args); err != nil {
|
if err := finalizeNamespace(args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -138,59 +131,6 @@ func setupEnv(args *InitArgs) error {
|
||||||
return nil
|
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
|
// Setup working directory
|
||||||
func setupWorkingDirectory(args *InitArgs) error {
|
func setupWorkingDirectory(args *InitArgs) error {
|
||||||
if args.WorkDir == "" {
|
if args.WorkDir == "" {
|
||||||
|
|
|
@ -2,74 +2,19 @@ package lxc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"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/namespaces"
|
||||||
"github.com/docker/libcontainer/security/capabilities"
|
|
||||||
"github.com/docker/libcontainer/system"
|
|
||||||
"github.com/docker/libcontainer/utils"
|
"github.com/docker/libcontainer/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setHostname(hostname string) error {
|
|
||||||
return syscall.Sethostname([]byte(hostname))
|
|
||||||
}
|
|
||||||
|
|
||||||
func finalizeNamespace(args *InitArgs) error {
|
func finalizeNamespace(args *InitArgs) error {
|
||||||
if err := utils.CloseExecFrom(3); err != nil {
|
if err := utils.CloseExecFrom(3); err != nil {
|
||||||
return err
|
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 {
|
if err := namespaces.SetupUser(args.User); err != nil {
|
||||||
return fmt.Errorf("setup user %s", err)
|
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 {
|
if err := setupWorkingDirectory(args); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,6 @@
|
||||||
|
|
||||||
package lxc
|
package lxc
|
||||||
|
|
||||||
func setHostname(hostname string) error {
|
|
||||||
panic("Not supported on darwin")
|
|
||||||
}
|
|
||||||
|
|
||||||
func finalizeNamespace(args *InitArgs) error {
|
func finalizeNamespace(args *InitArgs) error {
|
||||||
panic("Not supported on darwin")
|
panic("Not supported on darwin")
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package lxc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/docker/docker/daemon/execdriver"
|
"github.com/docker/docker/daemon/execdriver"
|
||||||
|
nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template"
|
||||||
"github.com/docker/libcontainer/label"
|
"github.com/docker/libcontainer/label"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -15,6 +16,13 @@ lxc.network.type = veth
|
||||||
lxc.network.link = {{.Network.Interface.Bridge}}
|
lxc.network.link = {{.Network.Interface.Bridge}}
|
||||||
lxc.network.name = eth0
|
lxc.network.name = eth0
|
||||||
lxc.network.mtu = {{.Network.Mtu}}
|
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}}
|
{{else if .Network.HostNetworking}}
|
||||||
lxc.network.type = none
|
lxc.network.type = none
|
||||||
{{else}}
|
{{else}}
|
||||||
|
@ -78,6 +86,18 @@ lxc.mount.entry = {{$value.Source}} {{escapeFstabSpaces $ROOTFS}}/{{escapeFstabS
|
||||||
{{end}}
|
{{end}}
|
||||||
{{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 .ProcessConfig.Privileged}}
|
||||||
{{if .AppArmor}}
|
{{if .AppArmor}}
|
||||||
lxc.aa_profile = unconfined
|
lxc.aa_profile = unconfined
|
||||||
|
@ -118,6 +138,19 @@ func escapeFstabSpaces(field string) string {
|
||||||
return strings.Replace(field, " ", "\\040", -1)
|
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 {
|
func isDirectory(source string) string {
|
||||||
f, err := os.Stat(source)
|
f, err := os.Stat(source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -152,6 +185,16 @@ func getLabel(c map[string][]string, name string) string {
|
||||||
return ""
|
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() {
|
func init() {
|
||||||
var err error
|
var err error
|
||||||
funcMap := template.FuncMap{
|
funcMap := template.FuncMap{
|
||||||
|
@ -159,6 +202,8 @@ func init() {
|
||||||
"escapeFstabSpaces": escapeFstabSpaces,
|
"escapeFstabSpaces": escapeFstabSpaces,
|
||||||
"formatMountLabel": label.FormatMountLabel,
|
"formatMountLabel": label.FormatMountLabel,
|
||||||
"isDirectory": isDirectory,
|
"isDirectory": isDirectory,
|
||||||
|
"keepCapabilities": keepCapabilities,
|
||||||
|
"getHostname": getHostname,
|
||||||
}
|
}
|
||||||
LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
|
LxcTemplateCompiled, err = template.New("lxc").Funcs(funcMap).Parse(LxcTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/docker/daemon/execdriver"
|
"github.com/docker/docker/daemon/execdriver"
|
||||||
|
nativeTemplate "github.com/docker/docker/daemon/execdriver/native/template"
|
||||||
"github.com/docker/libcontainer/devices"
|
"github.com/docker/libcontainer/devices"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -104,6 +105,10 @@ func TestCustomLxcConfig(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func grepFile(t *testing.T, path string, pattern string) {
|
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)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -117,9 +122,15 @@ func grepFile(t *testing.T, path string, pattern string) {
|
||||||
for err == nil {
|
for err == nil {
|
||||||
line, err = r.ReadString('\n')
|
line, err = r.ReadString('\n')
|
||||||
if strings.Contains(line, pattern) == true {
|
if strings.Contains(line, pattern) == true {
|
||||||
|
if inverseGrep {
|
||||||
|
t.Fatalf("grepFile: pattern \"%s\" found in \"%s\"", pattern, path)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if inverseGrep {
|
||||||
|
return
|
||||||
|
}
|
||||||
t.Fatalf("grepFile: pattern \"%s\" not found in \"%s\"", pattern, path)
|
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,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"))
|
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)
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче