From c28c63472a10440a136926ecdb27504fc205c144 Mon Sep 17 00:00:00 2001 From: Tibor Vass Date: Fri, 9 Sep 2016 09:27:53 -0700 Subject: [PATCH] plugins: linux capabilities and device creation In the plugin manifest, Capabilities has been moved to Linux.Capabilities to avoid confusion with Interface.Types[i].Capability A DeviceCreation boolean has also been added to the manifest. This could be changed in the future to be specific to a major number. Signed-off-by: Tibor Vass (cherry picked from commit 9f239281b1b02ed46f98af1eb39bc9b2165073fa) Signed-off-by: Victor Vieux --- api/swagger.yaml | 19 ++++++++++++++----- api/types/plugin.go | 21 +++++++++++++++++---- plugin/v2/plugin.go | 36 ++++++++++++++++++++++++++++-------- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/api/swagger.yaml b/api/swagger.yaml index f1d59d1ca4..1113cad2c7 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -1311,9 +1311,10 @@ definitions: - Entrypoint - Workdir - Network - - Capabilities + - Linux - Mounts - Devices + - DeviceCreation - Env - Args properties: @@ -1361,10 +1362,15 @@ definitions: Type: x-nullable: false type: "string" - Capabilities: - type: "array" - items: - type: "string" + Linux: + type: "object" + x-nullable: false + required: [Capabilities] + properties: + Capabilities: + type: "array" + items: + type: "string" Mounts: type: "array" items: @@ -1373,6 +1379,9 @@ definitions: type: "array" items: $ref: "#/definitions/PluginDevice" + DeviceCreation: + type: "boolean" + x-nullable: false Env: type: "array" items: diff --git a/api/types/plugin.go b/api/types/plugin.go index d3fc41439e..2c5c1d70b8 100644 --- a/api/types/plugin.go +++ b/api/types/plugin.go @@ -39,14 +39,14 @@ type PluginConfig struct { // Required: true Args PluginConfigArgs `json:"Args"` - // capabilities - // Required: true - Capabilities []string `json:"Capabilities"` - // description // Required: true Description string `json:"Description"` + // device creation + // Required: true + DeviceCreation bool `json:"DeviceCreation"` + // devices // Required: true Devices []PluginDevice `json:"Devices"` @@ -67,6 +67,10 @@ type PluginConfig struct { // Required: true Interface PluginConfigInterface `json:"Interface"` + // linux + // Required: true + Linux PluginConfigLinux `json:"Linux"` + // mounts // Required: true Mounts []PluginMount `json:"Mounts"` @@ -117,6 +121,15 @@ type PluginConfigInterface struct { Types []PluginInterfaceType `json:"Types"` } +// PluginConfigLinux plugin config linux +// swagger:model PluginConfigLinux +type PluginConfigLinux struct { + + // capabilities + // Required: true + Capabilities []string `json:"Capabilities"` +} + // PluginConfigNetwork plugin config network // swagger:model PluginConfigNetwork type PluginConfigNetwork struct { diff --git a/plugin/v2/plugin.go b/plugin/v2/plugin.go index 56775fce62..1dbffd275a 100644 --- a/plugin/v2/plugin.go +++ b/plugin/v2/plugin.go @@ -243,11 +243,18 @@ func (p *Plugin) ComputePrivileges() types.PluginPrivileges { }) } } - if len(m.Capabilities) > 0 { + if m.DeviceCreation { + privileges = append(privileges, types.PluginPrivilege{ + Name: "device-creation", + Description: "", + Value: []string{"true"}, + }) + } + if len(m.Linux.Capabilities) > 0 { privileges = append(privileges, types.PluginPrivilege{ Name: "capabilities", Description: "", - Value: m.Capabilities, + Value: m.Linux.Capabilities, }) } return privileges @@ -293,6 +300,11 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) { Readonly: false, // TODO: all plugins should be readonly? settable in config? } + if p.PluginObj.Config.DeviceCreation { + rwm := "rwm" + s.Linux.Resources.Devices = []specs.DeviceCgroup{{Allow: true, Access: &rwm}} + } + mounts := append(p.PluginObj.Settings.Mounts, types.PluginMount{ Source: &p.RuntimeSourcePath, Destination: defaultPluginRuntimeDestination, @@ -323,6 +335,12 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) { s.Mounts = append(s.Mounts, m) } + for i, m := range s.Mounts { + if strings.HasPrefix(m.Destination, "/dev/") && true { // TODO: && user specified /dev + s.Mounts = append(s.Mounts[:i], s.Mounts[i+1:]...) + } + } + envs := make([]string, 1, len(p.PluginObj.Settings.Env)+1) envs[0] = "PATH=" + system.DefaultPathEnv envs = append(envs, p.PluginObj.Settings.Env...) @@ -332,12 +350,14 @@ func (p *Plugin) InitSpec(s specs.Spec, libRoot string) (*specs.Spec, error) { if len(cwd) == 0 { cwd = "/" } - s.Process = specs.Process{ - Terminal: false, - Args: args, - Cwd: cwd, - Env: envs, - } + s.Process.Terminal = false + s.Process.Args = args + s.Process.Cwd = cwd + s.Process.Env = envs + + // TODO: what about duplicates? + // TODO: Should not need CAP_ prefix in manifest? + s.Process.Capabilities = append(s.Process.Capabilities, p.PluginObj.Config.Linux.Capabilities...) return &s, nil }