f64baec276
Update docs for allow_caps, cap_add, cap_drop in exec/java/docker driver pages. Also update upgrade guide with guidance on new default linux capabilities for exec and java drivers.
135 lines
3.1 KiB
Go
135 lines
3.1 KiB
Go
// Package capabilities is used for managing sets of linux capabilities.
|
|
package capabilities
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
type nothing struct{}
|
|
|
|
var null = nothing{}
|
|
|
|
// Set represents a group linux capabilities, implementing some useful set
|
|
// operations, taking care of name normalization, and sentinel value expansions.
|
|
//
|
|
// Linux capabilities can be expressed in multiple ways when working with docker
|
|
// and/or executor, along with Nomad configuration.
|
|
//
|
|
// Capability names may be upper or lower case, and may or may not be prefixed
|
|
// with "CAP_" or "cap_". On top of that, Nomad interprets the special name "all"
|
|
// and "ALL" to mean "all capabilities supported by the operating system".
|
|
type Set struct {
|
|
data map[string]nothing
|
|
}
|
|
|
|
// New creates a new Set setting caps as the initial elements.
|
|
func New(caps []string) *Set {
|
|
m := make(map[string]nothing, len(caps))
|
|
for _, c := range caps {
|
|
insert(m, c)
|
|
}
|
|
return &Set{data: m}
|
|
}
|
|
|
|
// Add cap into s.
|
|
func (s *Set) Add(cap string) {
|
|
insert(s.data, cap)
|
|
}
|
|
|
|
func insert(data map[string]nothing, cap string) {
|
|
switch name := normalize(cap); name {
|
|
case "":
|
|
case "all":
|
|
for k, v := range Supported().data {
|
|
data[k] = v
|
|
}
|
|
return
|
|
default:
|
|
data[name] = null
|
|
}
|
|
}
|
|
|
|
// Remove caps from s.
|
|
func (s *Set) Remove(caps []string) {
|
|
for _, c := range caps {
|
|
name := normalize(c)
|
|
if name == "all" {
|
|
s.data = make(map[string]nothing)
|
|
return
|
|
}
|
|
delete(s.data, name)
|
|
}
|
|
}
|
|
|
|
// Union returns of Set of elements of both s and b.
|
|
func (s *Set) Union(b *Set) *Set {
|
|
data := make(map[string]nothing)
|
|
for c := range s.data {
|
|
data[c] = null
|
|
}
|
|
for c := range b.data {
|
|
data[c] = null
|
|
}
|
|
return &Set{data: data}
|
|
}
|
|
|
|
// Difference returns the Set of elements of b not in s.
|
|
func (s *Set) Difference(b *Set) *Set {
|
|
data := make(map[string]nothing)
|
|
for c := range b.data {
|
|
if _, exists := s.data[c]; !exists {
|
|
data[c] = null
|
|
}
|
|
}
|
|
return &Set{data: data}
|
|
}
|
|
|
|
// Intersect returns the Set of elements in both s and b.
|
|
func (s *Set) Intersect(b *Set) *Set {
|
|
data := make(map[string]nothing)
|
|
for c := range s.data {
|
|
if _, exists := b.data[c]; exists {
|
|
data[c] = null
|
|
}
|
|
}
|
|
return &Set{data: data}
|
|
}
|
|
|
|
// Empty return true if no capabilities exist in s.
|
|
func (s *Set) Empty() bool {
|
|
return len(s.data) == 0
|
|
}
|
|
|
|
// String returns the normalized and sorted string representation of s.
|
|
func (s *Set) String() string {
|
|
return strings.Join(s.Slice(false), ", ")
|
|
}
|
|
|
|
// Slice returns a sorted slice of capabilities in s.
|
|
//
|
|
// upper - indicates whether to uppercase and prefix capabilities with CAP_
|
|
func (s *Set) Slice(upper bool) []string {
|
|
caps := make([]string, 0, len(s.data))
|
|
for c := range s.data {
|
|
if upper {
|
|
c = "CAP_" + strings.ToUpper(c)
|
|
}
|
|
caps = append(caps, c)
|
|
}
|
|
sort.Strings(caps)
|
|
return caps
|
|
}
|
|
|
|
// linux capabilities are often named in 4 possible ways - upper or lower case,
|
|
// and with or without a CAP_ prefix
|
|
//
|
|
// since we must do comparisons on cap names, always normalize the names before
|
|
// letting them into the Set data-structure
|
|
func normalize(name string) string {
|
|
spaces := strings.TrimSpace(name)
|
|
lower := strings.ToLower(spaces)
|
|
trim := strings.TrimPrefix(lower, "cap_")
|
|
return trim
|
|
}
|