Add support for ambient capabilities

Allow setting ambient capabilities, as a seperate option to the standard
ones. If you are running as a non root user you should use these.

Note that unless you add `CAP_DAC_OVERRIDE` and similar permissions you
need to be careful about file ownership. Added support to set ownership
in the `files` section to help out with this.

Signed-off-by: Justin Cormack <justin.cormack@docker.com>
This commit is contained in:
Justin Cormack 2017-06-30 13:44:49 +01:00
parent 70c5c2e1a0
commit 66b4aed239
3 changed files with 66 additions and 48 deletions

View File

@ -414,6 +414,8 @@ func filesystem(m Moby, tw *tar.Writer) error {
Name: root,
Typeflag: tar.TypeDir,
Mode: dirMode,
Uid: int(f.UID),
Gid: int(f.GID),
}
err := tw.WriteHeader(hdr)
if err != nil {
@ -423,36 +425,30 @@ func filesystem(m Moby, tw *tar.Writer) error {
}
}
addedFiles[f.Path] = true
hdr := &tar.Header{
Name: f.Path,
Mode: mode,
Uid: int(f.UID),
Gid: int(f.GID),
}
if f.Directory {
if f.Contents != nil {
return errors.New("Directory with contents not allowed")
}
hdr := &tar.Header{
Name: f.Path,
Typeflag: tar.TypeDir,
Mode: mode,
}
hdr.Typeflag = tar.TypeDir
err := tw.WriteHeader(hdr)
if err != nil {
return err
}
} else if f.Symlink != "" {
hdr := &tar.Header{
Name: f.Path,
Typeflag: tar.TypeSymlink,
Mode: mode,
Linkname: f.Symlink,
}
hdr.Typeflag = tar.TypeSymlink
hdr.Linkname = f.Symlink
err := tw.WriteHeader(hdr)
if err != nil {
return err
}
} else {
hdr := &tar.Header{
Name: f.Path,
Mode: mode,
Size: int64(len(contents)),
}
hdr.Size = int64(len(contents))
err := tw.WriteHeader(hdr)
if err != nil {
return err

View File

@ -27,15 +27,7 @@ type Moby struct {
Onboot []Image
Services []Image
Trust TrustConfig
Files []struct {
Path string
Directory bool
Symlink string
Contents *string
Source string
Optional bool
Mode string
}
Files []File
}
// TrustConfig is the type of a content trust config
@ -44,11 +36,25 @@ type TrustConfig struct {
Org []string
}
// File is the type of a file specification
type File struct {
Path string
Directory bool
Symlink string
Contents *string
Source string
Optional bool
Mode string
UID uint32 `yaml:"uid" json:"uid"`
GID uint32 `yaml:"gid" json:"gid"`
}
// Image is the type of an image config
type Image struct {
Name string `yaml:"name" json:"name"`
Image string `yaml:"image" json:"image"`
Capabilities *[]string `yaml:"capabilities" json:"capabilities,omitempty"`
Ambient *[]string `yaml:"ambient" json:"ambient,omitempty"`
Mounts *[]specs.Mount `yaml:"mounts" json:"mounts,omitempty"`
Binds *[]string `yaml:"binds" json:"binds,omitempty"`
Tmpfs *[]string `yaml:"tmpfs" json:"tmpfs,omitempty"`
@ -619,25 +625,13 @@ func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect) (specs.Spec, err
// TODO user, cgroup namespaces
caps := assignStrings(label.Capabilities, yaml.Capabilities)
for _, capability := range caps {
if capability == "none" || capability == "all" {
continue
}
found := false
for _, ac := range allCaps {
if ac == capability {
found = true
break
}
}
if !found {
return oci, fmt.Errorf("unknown capability: %s", capability)
}
// Capabilities
capCheck := map[string]bool{}
for _, capability := range allCaps {
capCheck[capability] = true
}
boundingSet := map[string]bool{}
caps := assignStrings(label.Capabilities, yaml.Capabilities)
if len(caps) == 1 {
switch cap := strings.ToLower(caps[0]); cap {
case "none":
@ -646,6 +640,31 @@ func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect) (specs.Spec, err
caps = allCaps[:]
}
}
for _, capability := range caps {
if !capCheck[capability] {
return oci, fmt.Errorf("unknown capability: %s", capability)
}
boundingSet[capability] = true
}
ambient := assignStrings(label.Ambient, yaml.Ambient)
if len(ambient) == 1 {
switch cap := strings.ToLower(ambient[0]); cap {
case "none":
ambient = []string{}
case "all":
ambient = allCaps[:]
}
}
for _, capability := range ambient {
if !capCheck[capability] {
return oci, fmt.Errorf("unknown capability: %s", capability)
}
boundingSet[capability] = true
}
bounding := []string{}
for capability := range boundingSet {
bounding = append(bounding, capability)
}
rlimitsString := assignStrings(label.Rlimits, yaml.Rlimits)
rlimits := []specs.LinuxRlimit{}
@ -727,11 +746,11 @@ func ConfigInspectToOCI(yaml Image, inspect types.ImageInspect) (specs.Spec, err
Env: env,
Cwd: cwd,
Capabilities: &specs.LinuxCapabilities{
Bounding: caps,
Bounding: bounding,
Effective: caps,
Inheritable: caps,
Permitted: caps,
Ambient: []string{},
Inheritable: bounding,
Permitted: bounding,
Ambient: ambient,
},
Rlimits: rlimits,
NoNewPrivileges: assignBool(label.NoNewPrivileges, yaml.NoNewPrivileges),

View File

@ -24,7 +24,9 @@ var schema = string(`
"contents": {"type": "string"},
"source": {"type": "string"},
"optional": {"type": "boolean"},
"mode": {"type": "string"}
"mode": {"type": "string"},
"uid": {"type": "integer"},
"gid": {"type": "integer"}
}
},
"files": {
@ -65,6 +67,7 @@ var schema = string(`
"name": {"type": "string"},
"image": {"type": "string"},
"capabilities": { "$ref": "#/definitions/strings" },
"ambient": { "$ref": "#/definitions/strings" },
"mounts": { "$ref": "#/definitions/mounts" },
"binds": { "$ref": "#/definitions/strings" },
"tmpfs": { "$ref": "#/definitions/strings" },