github.com/xeptore/docker-cli@v20.10.14+incompatible/opts/capabilities.go (about)

     1  package opts
     2  
     3  import (
     4  	"sort"
     5  	"strings"
     6  )
     7  
     8  const (
     9  	// AllCapabilities is a special value to add or drop all capabilities
    10  	AllCapabilities = "ALL"
    11  
    12  	// ResetCapabilities is a special value to reset capabilities when updating.
    13  	// This value should only be used when updating, not used on "create".
    14  	ResetCapabilities = "RESET"
    15  )
    16  
    17  // NormalizeCapability normalizes a capability by upper-casing, trimming white space
    18  // and adding a CAP_ prefix (if not yet present). This function also accepts the
    19  // "ALL" magic-value, as used by CapAdd/CapDrop.
    20  //
    21  // This function only handles rudimentary formatting; no validation is performed,
    22  // as the list of available capabilities can be updated over time, thus should be
    23  // handled by the daemon.
    24  func NormalizeCapability(cap string) string {
    25  	cap = strings.ToUpper(strings.TrimSpace(cap))
    26  	if cap == AllCapabilities || cap == ResetCapabilities {
    27  		return cap
    28  	}
    29  	if !strings.HasPrefix(cap, "CAP_") {
    30  		cap = "CAP_" + cap
    31  	}
    32  	return cap
    33  }
    34  
    35  // CapabilitiesMap normalizes the given capabilities and converts them to a map.
    36  func CapabilitiesMap(caps []string) map[string]bool {
    37  	normalized := make(map[string]bool)
    38  	for _, c := range caps {
    39  		normalized[NormalizeCapability(c)] = true
    40  	}
    41  	return normalized
    42  }
    43  
    44  // EffectiveCapAddCapDrop normalizes and sorts capabilities to "add" and "drop",
    45  // and returns the effective capabilities to include in both.
    46  //
    47  // "CapAdd" takes precedence over "CapDrop", so capabilities included in both
    48  // lists are removed from the list of capabilities to drop. The special "ALL"
    49  // capability is also taken into account.
    50  //
    51  // Note that the special "RESET" value is only used when updating an existing
    52  // service, and will be ignored.
    53  //
    54  // Duplicates are removed, and the resulting lists are sorted.
    55  func EffectiveCapAddCapDrop(add, drop []string) (capAdd, capDrop []string) {
    56  	var (
    57  		addCaps  = CapabilitiesMap(add)
    58  		dropCaps = CapabilitiesMap(drop)
    59  	)
    60  
    61  	if addCaps[AllCapabilities] {
    62  		// Special case: "ALL capabilities" trumps any other capability added.
    63  		addCaps = map[string]bool{AllCapabilities: true}
    64  	}
    65  	if dropCaps[AllCapabilities] {
    66  		// Special case: "ALL capabilities" trumps any other capability added.
    67  		dropCaps = map[string]bool{AllCapabilities: true}
    68  	}
    69  	for c := range dropCaps {
    70  		if addCaps[c] {
    71  			// Adding a capability takes precedence, so skip dropping
    72  			continue
    73  		}
    74  		if c != ResetCapabilities {
    75  			capDrop = append(capDrop, c)
    76  		}
    77  	}
    78  
    79  	for c := range addCaps {
    80  		if c != ResetCapabilities {
    81  			capAdd = append(capAdd, c)
    82  		}
    83  	}
    84  
    85  	sort.Strings(capAdd)
    86  	sort.Strings(capDrop)
    87  
    88  	return capAdd, capDrop
    89  }