forked from toolshed/abra
		
	
		
			
				
	
	
		
			90 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 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(capability string) string {
 | |
| 	capability = strings.ToUpper(strings.TrimSpace(capability))
 | |
| 	if capability == AllCapabilities || capability == ResetCapabilities {
 | |
| 		return capability
 | |
| 	}
 | |
| 	if !strings.HasPrefix(capability, "CAP_") {
 | |
| 		capability = "CAP_" + capability
 | |
| 	}
 | |
| 	return capability
 | |
| }
 | |
| 
 | |
| // 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
 | |
| }
 |