1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/daemon/caps/utils.go
John Starks 349aeeab7c lcow: Allow the client to add or remove capabilities
Signed-off-by: John Starks <jostarks@microsoft.com>
2018-06-15 16:03:33 -07:00

139 lines
3.3 KiB
Go

package caps // import "github.com/docker/docker/daemon/caps"
import (
"fmt"
"strings"
"github.com/syndtr/gocapability/capability"
)
var capabilityList Capabilities
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,
&CapabilityMapping{
Key: "CAP_" + strings.ToUpper(cap.String()),
Value: cap,
},
)
}
}
type (
// CapabilityMapping maps linux capability name to its value of capability.Cap type
// Capabilities is one of the security systems in Linux Security Module (LSM)
// framework provided by the kernel.
// For more details on capabilities, see http://man7.org/linux/man-pages/man7/capabilities.7.html
CapabilityMapping struct {
Key string `json:"key,omitempty"`
Value capability.Cap `json:"value,omitempty"`
}
// Capabilities contains all CapabilityMapping
Capabilities []*CapabilityMapping
)
// String returns <key> of CapabilityMapping
func (c *CapabilityMapping) String() string {
return c.Key
}
// GetCapability returns CapabilityMapping which contains specific key
func GetCapability(key string) *CapabilityMapping {
for _, capp := range capabilityList {
if capp.Key == key {
cpy := *capp
return &cpy
}
}
return nil
}
// GetAllCapabilities returns all of the capabilities
func GetAllCapabilities() []string {
output := make([]string, len(capabilityList))
for i, capability := range capabilityList {
output[i] = capability.String()
}
return output
}
// inSlice tests whether a string is contained in a slice of strings or not.
// Comparison is case insensitive
func inSlice(slice []string, s string) bool {
for _, ss := range slice {
if strings.ToLower(s) == strings.ToLower(ss) {
return true
}
}
return false
}
// TweakCapabilities can tweak capabilities by adding or dropping capabilities
// based on the basics capabilities.
func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
var (
newCaps []string
allCaps = GetAllCapabilities()
)
// FIXME(tonistiigi): docker format is without CAP_ prefix, oci is with prefix
// Currently they are mixed in here. We should do conversion in one place.
// look for invalid cap in the drop list
for _, cap := range drops {
if strings.ToLower(cap) == "all" {
continue
}
if !inSlice(allCaps, "CAP_"+cap) {
return nil, fmt.Errorf("Unknown capability drop: %q", cap)
}
}
// handle --cap-add=all
if inSlice(adds, "all") {
basics = allCaps
}
if !inSlice(drops, "all") {
for _, cap := range basics {
// skip `all` already handled above
if strings.ToLower(cap) == "all" {
continue
}
// if we don't drop `all`, add back all the non-dropped caps
if !inSlice(drops, cap[4:]) {
newCaps = append(newCaps, strings.ToUpper(cap))
}
}
}
for _, cap := range adds {
// skip `all` already handled above
if strings.ToLower(cap) == "all" {
continue
}
cap = "CAP_" + cap
if !inSlice(allCaps, cap) {
return nil, fmt.Errorf("Unknown capability to add: %q", cap)
}
// add cap if not already in the list
if !inSlice(newCaps, cap) {
newCaps = append(newCaps, strings.ToUpper(cap))
}
}
return newCaps, nil
}