diff --git a/go.mod b/go.mod index 9daab069..f9e8abb0 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/containers/skopeo go 1.12 require ( - github.com/containers/common v0.23.0 + github.com/containers/common v0.24.0 github.com/containers/image/v5 v5.6.0 github.com/containers/ocicrypt v1.0.3 github.com/containers/storage v1.23.5 diff --git a/go.sum b/go.sum index dd532bdb..0516da08 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/containers/common v0.23.0 h1:+g4mI3wUYSzOtoWU9TNVoV4K52/aN6JEz0qs1YdPEe8= -github.com/containers/common v0.23.0/go.mod h1:E56/N0beWGf+lrrJX32atuo2hkjzHwSC8n1vCG+TAR0= +github.com/containers/common v0.24.0 h1:5C03ROzmRvZCyooNJVkZ4Q8T2d04g+VVyPMQ428XC4Y= +github.com/containers/common v0.24.0/go.mod h1:BFRo6uRh1TbkZgR2oYTILxc2BNZTBtBffa9xtu881QI= github.com/containers/image/v5 v5.6.0 h1:r4AqIX4NO/X7OJkqX574zITV3fq0ZPn0pSlLsxWF6ww= github.com/containers/image/v5 v5.6.0/go.mod h1:iUSWo3SOLqJo0CkZkKrHxqR6YWqrT98mkXFpE0MceE8= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= diff --git a/vendor/github.com/containers/common/pkg/capabilities/capabilities.go b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go new file mode 100644 index 00000000..ddfa53be --- /dev/null +++ b/vendor/github.com/containers/common/pkg/capabilities/capabilities.go @@ -0,0 +1,156 @@ +package capabilities + +// Copyright 2013-2018 Docker, Inc. + +// NOTE: this package has been copied from github.com/docker/docker but been +// changed significantly to fit the needs of libpod. + +import ( + "strings" + + "github.com/pkg/errors" + "github.com/syndtr/gocapability/capability" +) + +var ( + // Used internally and populated during init(). + capabilityList []string + + // ErrUnknownCapability is thrown when an unknown capability is processed. + ErrUnknownCapability = errors.New("unknown capability") + + // ContainerImageLabels - label can indicate the required + // capabilities required by containers to run the container image. + ContainerImageLabels = []string{"io.containers.capabilities"} +) + +// All is a special value used to add/drop all known capababilities. +// Useful on the CLI for `--cap-add=all` etc. +const All = "ALL" + +func init() { + last := capability.CAP_LAST_CAP + // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap + if last == capability.Cap(63) { + last = capability.CAP_BLOCK_SUSPEND + } + for _, cap := range capability.List() { + if cap > last { + continue + } + capabilityList = append(capabilityList, "CAP_"+strings.ToUpper(cap.String())) + } +} + +// stringInSlice determines if a string is in a string slice, returns bool +func stringInSlice(s string, sl []string) bool { + for _, i := range sl { + if i == s { + return true + } + } + return false +} + +// AllCapabilities returns all known capabilities. +func AllCapabilities() []string { + return capabilityList +} + +// NormalizeCapabilities normalizes caps by adding a "CAP_" prefix (if not yet +// present). +func NormalizeCapabilities(caps []string) ([]string, error) { + normalized := make([]string, len(caps)) + for i, c := range caps { + c = strings.ToUpper(c) + if c == All { + normalized = append(normalized, c) + continue + } + if !strings.HasPrefix(c, "CAP_") { + c = "CAP_" + c + } + if !stringInSlice(c, capabilityList) { + return nil, errors.Wrapf(ErrUnknownCapability, "%q", c) + } + normalized[i] = c + } + return normalized, nil +} + +// ValidateCapabilities validates if caps only contains valid capabilities. +func ValidateCapabilities(caps []string) error { + for _, c := range caps { + if !stringInSlice(c, capabilityList) { + return errors.Wrapf(ErrUnknownCapability, "%q", c) + } + } + return nil +} + +// MergeCapabilities computes a set of capabilities by adding capapbitilities +// to or dropping them from base. +// +// Note that: +// "ALL" in capAdd adds returns known capabilities +// "All" in capDrop returns only the capabilities specified in capAdd +func MergeCapabilities(base, adds, drops []string) ([]string, error) { + var caps []string + + // Normalize the base capabilities + base, err := NormalizeCapabilities(base) + if err != nil { + return nil, err + } + if len(adds) == 0 && len(drops) == 0 { + // Nothing to tweak; we're done + return base, nil + } + capDrop, err := NormalizeCapabilities(drops) + if err != nil { + return nil, err + } + capAdd, err := NormalizeCapabilities(adds) + if err != nil { + return nil, err + } + + if stringInSlice(All, capDrop) { + // "Drop" all capabilities; return what's in capAdd instead + return capAdd, nil + } + + if stringInSlice(All, capAdd) { + // "Add" all capabilities; + return capabilityList, nil + } + + for _, add := range capAdd { + if stringInSlice(add, capDrop) { + return nil, errors.Errorf("capability %q cannot be dropped and added", add) + } + } + + for _, drop := range capDrop { + if stringInSlice(drop, capAdd) { + return nil, errors.Errorf("capability %q cannot be dropped and added", drop) + } + } + + // Drop any capabilities in capDrop that are in base + for _, cap := range base { + if stringInSlice(cap, capDrop) { + continue + } + caps = append(caps, cap) + } + + // Add any capabilities in capAdd that are not in base + for _, cap := range capAdd { + if stringInSlice(cap, base) { + continue + } + caps = append(caps, cap) + } + return caps, nil +} diff --git a/vendor/github.com/containers/common/pkg/completion/completion.go b/vendor/github.com/containers/common/pkg/completion/completion.go index 6e7ddff3..07451e99 100644 --- a/vendor/github.com/containers/common/pkg/completion/completion.go +++ b/vendor/github.com/containers/common/pkg/completion/completion.go @@ -1,6 +1,14 @@ package completion -import "github.com/spf13/cobra" +import ( + "bufio" + "os" + "strings" + "unicode" + + "github.com/containers/common/pkg/capabilities" + "github.com/spf13/cobra" +) // FlagCompletions - hold flag completion functions to be applied later with CompleteCommandFlags() type FlagCompletions map[string]func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) @@ -24,3 +32,62 @@ func AutocompleteNone(cmd *cobra.Command, args []string, toComplete string) ([]s func AutocompleteDefault(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveDefault } + +// AutocompleteCapabilities - Autocomplete linux capabilities options. +// Used by --cap-add and --cap-drop. +func AutocompleteCapabilities(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + caps := capabilities.AllCapabilities() + + // convertCase will convert a string to lowercase only if the user input is lowercase + convertCase := func(s string) string { return s } + if len(toComplete) > 0 && unicode.IsLower(rune(toComplete[0])) { + convertCase = strings.ToLower + } + + // offset is used to trim "CAP_" if the user doesn't type CA... or ca... + offset := 0 + if !strings.HasPrefix(toComplete, convertCase("CA")) { + // setting the offset to 4 is safe since each cap starts with CAP_ + offset = 4 + } + + var completions []string + for _, cap := range caps { + completions = append(completions, convertCase(cap)[offset:]) + } + + // add ALL here which is also a valid argument + completions = append(completions, convertCase(capabilities.All)) + return completions, cobra.ShellCompDirectiveNoFileComp +} + +// autocompleteSubIDName - autocomplete the names in /etc/subuid or /etc/subgid +func autocompleteSubIDName(filename string) ([]string, cobra.ShellCompDirective) { + file, err := os.Open(filename) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + defer file.Close() + + var names []string + scanner := bufio.NewScanner(file) + for scanner.Scan() { + name := strings.SplitN(scanner.Text(), ":", 2)[0] + names = append(names, name) + } + if err = scanner.Err(); err != nil { + return nil, cobra.ShellCompDirectiveError + } + + return names, cobra.ShellCompDirectiveNoFileComp +} + +// AutocompleteSubgidName - Autocomplete subgidname based on the names in the /etc/subgid file. +func AutocompleteSubgidName(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return autocompleteSubIDName("/etc/subgid") +} + +// AutocompleteSubuidName - Autocomplete subuidname based on the names in the /etc/subuid file. +func AutocompleteSubuidName(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + return autocompleteSubIDName("/etc/subuid") +} diff --git a/vendor/modules.txt b/vendor/modules.txt index d6a5d74e..d7da0028 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -35,8 +35,9 @@ github.com/beorn7/perks/quantile github.com/containerd/cgroups/stats/v1 # github.com/containerd/containerd v1.3.2 github.com/containerd/containerd/errdefs -# github.com/containers/common v0.23.0 +# github.com/containers/common v0.24.0 github.com/containers/common/pkg/auth +github.com/containers/common/pkg/capabilities github.com/containers/common/pkg/completion github.com/containers/common/pkg/retry # github.com/containers/image/v5 v5.6.0