File: capabilities.go

package info (click to toggle)
docker.io 20.10.24%2Bdfsg1-1%2Bdeb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bookworm-proposed-updates
  • size: 60,824 kB
  • sloc: sh: 5,621; makefile: 593; ansic: 179; python: 162; asm: 7
file content (89 lines) | stat: -rw-r--r-- 2,607 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package opts

import (
	"sort"
	"strings"
)

const (
	// AllCapabilities is a special value to add or drop all capabilities
	AllCapabilities = "ALL"

	// ResetCapabilities is a special value to reset capabilities when updating.
	// This value should only be used when updating, not used on "create".
	ResetCapabilities = "RESET"
)

// NormalizeCapability normalizes a capability by upper-casing, trimming white space
// and adding a CAP_ prefix (if not yet present). This function also accepts the
// "ALL" magic-value, as used by CapAdd/CapDrop.
//
// This function only handles rudimentary formatting; no validation is performed,
// as the list of available capabilities can be updated over time, thus should be
// handled by the daemon.
func NormalizeCapability(cap string) string {
	cap = strings.ToUpper(strings.TrimSpace(cap))
	if cap == AllCapabilities || cap == ResetCapabilities {
		return cap
	}
	if !strings.HasPrefix(cap, "CAP_") {
		cap = "CAP_" + cap
	}
	return cap
}

// CapabilitiesMap normalizes the given capabilities and converts them to a map.
func CapabilitiesMap(caps []string) map[string]bool {
	normalized := make(map[string]bool)
	for _, c := range caps {
		normalized[NormalizeCapability(c)] = true
	}
	return normalized
}

// EffectiveCapAddCapDrop normalizes and sorts capabilities to "add" and "drop",
// and returns the effective capabilities to include in both.
//
// "CapAdd" takes precedence over "CapDrop", so capabilities included in both
// lists are removed from the list of capabilities to drop. The special "ALL"
// capability is also taken into account.
//
// Note that the special "RESET" value is only used when updating an existing
// service, and will be ignored.
//
// Duplicates are removed, and the resulting lists are sorted.
func EffectiveCapAddCapDrop(add, drop []string) (capAdd, capDrop []string) {
	var (
		addCaps  = CapabilitiesMap(add)
		dropCaps = CapabilitiesMap(drop)
	)

	if addCaps[AllCapabilities] {
		// Special case: "ALL capabilities" trumps any other capability added.
		addCaps = map[string]bool{AllCapabilities: true}
	}
	if dropCaps[AllCapabilities] {
		// Special case: "ALL capabilities" trumps any other capability added.
		dropCaps = map[string]bool{AllCapabilities: true}
	}
	for c := range dropCaps {
		if addCaps[c] {
			// Adding a capability takes precedence, so skip dropping
			continue
		}
		if c != ResetCapabilities {
			capDrop = append(capDrop, c)
		}
	}

	for c := range addCaps {
		if c != ResetCapabilities {
			capAdd = append(capAdd, c)
		}
	}

	sort.Strings(capAdd)
	sort.Strings(capDrop)

	return capAdd, capDrop
}