Replace usage of Whitelist with Allowlist within Kubelet's sysctl package (#102298)

* Change uses of whitelist to allowlist in kubelet sysctl

* Rename whitelist files to allowlist in Kubelet sysctl

* Further renames of whitelist to allowlist in Kubelet

* Rename podsecuritypolicy uses of whitelist to allowlist

* Update pkg/kubelet/kubelet.go

Co-authored-by: Danielle <dani@builds.terrible.systems>

Co-authored-by: Danielle <dani@builds.terrible.systems>
This commit is contained in:
Wesley Williams 2021-08-05 02:59:35 +01:00 committed by GitHub
parent 9c5cefb230
commit ff165c8823
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 49 additions and 49 deletions

View File

@ -340,7 +340,7 @@ type KubeletConfiguration struct {
ContainerLogMaxFiles int32 ContainerLogMaxFiles int32
// ConfigMapAndSecretChangeDetectionStrategy is a mode in which config map and secret managers are running. // ConfigMapAndSecretChangeDetectionStrategy is a mode in which config map and secret managers are running.
ConfigMapAndSecretChangeDetectionStrategy ResourceChangeDetectionStrategy ConfigMapAndSecretChangeDetectionStrategy ResourceChangeDetectionStrategy
// A comma separated whitelist of unsafe sysctls or sysctl patterns (ending in *). // A comma separated allowlist of unsafe sysctls or sysctl patterns (ending in *).
// Unsafe sysctl groups are kernel.shm*, kernel.msg*, kernel.sem, fs.mqueue.*, and net.*. // Unsafe sysctl groups are kernel.shm*, kernel.msg*, kernel.sem, fs.mqueue.*, and net.*.
// These sysctls are namespaced but not allowed by default. For example: "kernel.msg*,net.ipv4.route.min_pmtu" // These sysctls are namespaced but not allowed by default. For example: "kernel.msg*,net.ipv4.route.min_pmtu"
// +optional // +optional

View File

@ -279,16 +279,16 @@ func (m *cgroupManagerImpl) Exists(name CgroupName) bool {
// scoped to the set control groups it understands. this is being discussed // scoped to the set control groups it understands. this is being discussed
// in https://github.com/opencontainers/runc/issues/1440 // in https://github.com/opencontainers/runc/issues/1440
// once resolved, we can remove this code. // once resolved, we can remove this code.
whitelistControllers := sets.NewString("cpu", "cpuacct", "cpuset", "memory", "systemd", "pids") allowlistControllers := sets.NewString("cpu", "cpuacct", "cpuset", "memory", "systemd", "pids")
if _, ok := m.subsystems.MountPoints["hugetlb"]; ok { if _, ok := m.subsystems.MountPoints["hugetlb"]; ok {
whitelistControllers.Insert("hugetlb") allowlistControllers.Insert("hugetlb")
} }
var missingPaths []string var missingPaths []string
// If even one cgroup path doesn't exist, then the cgroup doesn't exist. // If even one cgroup path doesn't exist, then the cgroup doesn't exist.
for controller, path := range cgroupPaths { for controller, path := range cgroupPaths {
// ignore mounts we don't care about // ignore mounts we don't care about
if !whitelistControllers.Has(controller) { if !allowlistControllers.Has(controller) {
continue continue
} }
if !libcontainercgroups.PathExists(path) { if !libcontainercgroups.PathExists(path) {

View File

@ -112,7 +112,7 @@ import (
"k8s.io/kubernetes/pkg/kubelet/util/sliceutils" "k8s.io/kubernetes/pkg/kubelet/util/sliceutils"
"k8s.io/kubernetes/pkg/kubelet/volumemanager" "k8s.io/kubernetes/pkg/kubelet/volumemanager"
"k8s.io/kubernetes/pkg/security/apparmor" "k8s.io/kubernetes/pkg/security/apparmor"
sysctlwhitelist "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl" sysctlallowlist "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl"
"k8s.io/kubernetes/pkg/util/oom" "k8s.io/kubernetes/pkg/util/oom"
"k8s.io/kubernetes/pkg/util/selinux" "k8s.io/kubernetes/pkg/util/selinux"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
@ -820,14 +820,14 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
klet.evictionManager = evictionManager klet.evictionManager = evictionManager
klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler) klet.admitHandlers.AddPodAdmitHandler(evictionAdmitHandler)
// Safe, whitelisted sysctls can always be used as unsafe sysctls in the spec. // Safe, allowed sysctls can always be used as unsafe sysctls in the spec.
// Hence, we concatenate those two lists. // Hence, we concatenate those two lists.
safeAndUnsafeSysctls := append(sysctlwhitelist.SafeSysctlWhitelist(), allowedUnsafeSysctls...) safeAndUnsafeSysctls := append(sysctlallowlist.SafeSysctlAllowlist(), allowedUnsafeSysctls...)
sysctlsWhitelist, err := sysctl.NewWhitelist(safeAndUnsafeSysctls) sysctlsAllowlist, err := sysctl.NewAllowlist(safeAndUnsafeSysctls)
if err != nil { if err != nil {
return nil, err return nil, err
} }
klet.admitHandlers.AddPodAdmitHandler(sysctlsWhitelist) klet.admitHandlers.AddPodAdmitHandler(sysctlsAllowlist)
// enable active deadline handler // enable active deadline handler
activeDeadlineHandler, err := newActiveDeadlineHandler(klet.statusManager, kubeDeps.Recorder, klet.clock) activeDeadlineHandler, err := newActiveDeadlineHandler(klet.statusManager, kubeDeps.Recorder, klet.clock)

View File

@ -1791,7 +1791,7 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
// ServeLogs returns logs of current machine. // ServeLogs returns logs of current machine.
func (kl *Kubelet) ServeLogs(w http.ResponseWriter, req *http.Request) { func (kl *Kubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
// TODO: whitelist logs we are willing to serve // TODO: allowlist logs we are willing to serve
kl.logServer.ServeHTTP(w, req) kl.logServer.ServeHTTP(w, req)
} }

View File

@ -30,19 +30,19 @@ const (
ForbiddenReason = "SysctlForbidden" ForbiddenReason = "SysctlForbidden"
) )
// patternWhitelist takes a list of sysctls or sysctl patterns (ending in *) and // patternAllowlist takes a list of sysctls or sysctl patterns (ending in *) and
// checks validity via a sysctl and prefix map, rejecting those which are not known // checks validity via a sysctl and prefix map, rejecting those which are not known
// to be namespaced. // to be namespaced.
type patternWhitelist struct { type patternAllowlist struct {
sysctls map[string]Namespace sysctls map[string]Namespace
prefixes map[string]Namespace prefixes map[string]Namespace
} }
var _ lifecycle.PodAdmitHandler = &patternWhitelist{} var _ lifecycle.PodAdmitHandler = &patternAllowlist{}
// NewWhitelist creates a new Whitelist from a list of sysctls and sysctl pattern (ending in *). // NewAllowlist creates a new Allowlist from a list of sysctls and sysctl pattern (ending in *).
func NewWhitelist(patterns []string) (*patternWhitelist, error) { func NewAllowlist(patterns []string) (*patternAllowlist, error) {
w := &patternWhitelist{ w := &patternAllowlist{
sysctls: map[string]Namespace{}, sysctls: map[string]Namespace{},
prefixes: map[string]Namespace{}, prefixes: map[string]Namespace{},
} }
@ -73,14 +73,14 @@ func NewWhitelist(patterns []string) (*patternWhitelist, error) {
return w, nil return w, nil
} }
// validateSysctl checks that a sysctl is whitelisted because it is known // validateSysctl checks that a sysctl is allowlisted because it is known
// to be namespaced by the Linux kernel. Note that being whitelisted is required, but not // to be namespaced by the Linux kernel. Note that being allowlisted is required, but not
// sufficient: the container runtime might have a stricter check and refuse to launch a pod. // sufficient: the container runtime might have a stricter check and refuse to launch a pod.
// //
// The parameters hostNet and hostIPC are used to forbid sysctls for pod sharing the // The parameters hostNet and hostIPC are used to forbid sysctls for pod sharing the
// respective namespaces with the host. This check is only possible for sysctls on // respective namespaces with the host. This check is only possible for sysctls on
// the static default whitelist, not those on the custom whitelist provided by the admin. // the static default allowlist, not those on the custom allowlist provided by the admin.
func (w *patternWhitelist) validateSysctl(sysctl string, hostNet, hostIPC bool) error { func (w *patternAllowlist) validateSysctl(sysctl string, hostNet, hostIPC bool) error {
nsErrorFmt := "%q not allowed with host %s enabled" nsErrorFmt := "%q not allowed with host %s enabled"
if ns, found := w.sysctls[sysctl]; found { if ns, found := w.sysctls[sysctl]; found {
if ns == ipcNamespace && hostIPC { if ns == ipcNamespace && hostIPC {
@ -102,12 +102,12 @@ func (w *patternWhitelist) validateSysctl(sysctl string, hostNet, hostIPC bool)
return nil return nil
} }
} }
return fmt.Errorf("%q not whitelisted", sysctl) return fmt.Errorf("%q not allowlisted", sysctl)
} }
// Admit checks that all sysctls given in pod's security context // Admit checks that all sysctls given in pod's security context
// are valid according to the whitelist. // are valid according to the allowlist.
func (w *patternWhitelist) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult { func (w *patternAllowlist) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult {
pod := attrs.Pod pod := attrs.Pod
if pod.Spec.SecurityContext == nil || len(pod.Spec.SecurityContext.Sysctls) == 0 { if pod.Spec.SecurityContext == nil || len(pod.Spec.SecurityContext.Sysctls) == 0 {
return lifecycle.PodAdmitResult{ return lifecycle.PodAdmitResult{

View File

@ -22,7 +22,7 @@ import (
"k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl" "k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl"
) )
func TestNewWhitelist(t *testing.T) { func TestNewAllowlist(t *testing.T) {
type Test struct { type Test struct {
sysctls []string sysctls []string
err bool err bool
@ -35,16 +35,16 @@ func TestNewWhitelist(t *testing.T) {
{sysctls: []string{"net.*.foo"}, err: true}, {sysctls: []string{"net.*.foo"}, err: true},
{sysctls: []string{"foo"}, err: true}, {sysctls: []string{"foo"}, err: true},
} { } {
_, err := NewWhitelist(append(sysctl.SafeSysctlWhitelist(), test.sysctls...)) _, err := NewAllowlist(append(sysctl.SafeSysctlAllowlist(), test.sysctls...))
if test.err && err == nil { if test.err && err == nil {
t.Errorf("expected an error creating a whitelist for %v", test.sysctls) t.Errorf("expected an error creating a allowlist for %v", test.sysctls)
} else if !test.err && err != nil { } else if !test.err && err != nil {
t.Errorf("got unexpected error creating a whitelist for %v: %v", test.sysctls, err) t.Errorf("got unexpected error creating a allowlist for %v: %v", test.sysctls, err)
} }
} }
} }
func TestWhitelist(t *testing.T) { func TestAllowlist(t *testing.T) {
type Test struct { type Test struct {
sysctl string sysctl string
hostNet, hostIPC bool hostNet, hostIPC bool
@ -65,14 +65,14 @@ func TestWhitelist(t *testing.T) {
{sysctl: "kernel.sem", hostIPC: true}, {sysctl: "kernel.sem", hostIPC: true},
} }
w, err := NewWhitelist(append(sysctl.SafeSysctlWhitelist(), "kernel.msg*", "kernel.sem")) w, err := NewAllowlist(append(sysctl.SafeSysctlAllowlist(), "kernel.msg*", "kernel.sem"))
if err != nil { if err != nil {
t.Fatalf("failed to create whitelist: %v", err) t.Fatalf("failed to create allowlist: %v", err)
} }
for _, test := range valid { for _, test := range valid {
if err := w.validateSysctl(test.sysctl, test.hostNet, test.hostIPC); err != nil { if err := w.validateSysctl(test.sysctl, test.hostNet, test.hostIPC); err != nil {
t.Errorf("expected to be whitelisted: %+v, got: %v", test, err) t.Errorf("expected to be allowlisted: %+v, got: %v", test, err)
} }
} }

View File

@ -83,7 +83,7 @@ func (f *simpleStrategyFactory) CreateStrategies(psp *policy.PodSecurityPolicy,
errs = append(errs, err) errs = append(errs, err)
} }
sysctlsStrat := createSysctlsStrategy(sysctl.SafeSysctlWhitelist(), psp.Spec.AllowedUnsafeSysctls, psp.Spec.ForbiddenSysctls) sysctlsStrat := createSysctlsStrategy(sysctl.SafeSysctlAllowlist(), psp.Spec.AllowedUnsafeSysctls, psp.Spec.ForbiddenSysctls)
if len(errs) > 0 { if len(errs) > 0 {
return nil, errors.NewAggregate(errs) return nil, errors.NewAggregate(errs)
@ -191,6 +191,6 @@ func createCapabilitiesStrategy(defaultAddCaps, requiredDropCaps, allowedCaps []
} }
// createSysctlsStrategy creates a new sysctls strategy. // createSysctlsStrategy creates a new sysctls strategy.
func createSysctlsStrategy(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) sysctl.SysctlsStrategy { func createSysctlsStrategy(safeAllowlist, allowedUnsafeSysctls, forbiddenSysctls []string) sysctl.SysctlsStrategy {
return sysctl.NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls) return sysctl.NewMustMatchPatterns(safeAllowlist, allowedUnsafeSysctls, forbiddenSysctls)
} }

View File

@ -1006,19 +1006,19 @@ func TestValidatePodSuccess(t *testing.T) {
pod: seccompPod, pod: seccompPod,
psp: seccompPSP, psp: seccompPSP,
}, },
"flex volume driver in a whitelist (all volumes are allowed)": { "flex volume driver in a allowlist (all volumes are allowed)": {
pod: flexVolumePod, pod: flexVolumePod,
psp: allowFlexVolumesPSP(false, true), psp: allowFlexVolumesPSP(false, true),
}, },
"flex volume driver with empty whitelist (all volumes are allowed)": { "flex volume driver with empty allowlist (all volumes are allowed)": {
pod: flexVolumePod, pod: flexVolumePod,
psp: allowFlexVolumesPSP(true, true), psp: allowFlexVolumesPSP(true, true),
}, },
"flex volume driver in a whitelist (only flex volumes are allowed)": { "flex volume driver in a allowlist (only flex volumes are allowed)": {
pod: flexVolumePod, pod: flexVolumePod,
psp: allowFlexVolumesPSP(false, false), psp: allowFlexVolumesPSP(false, false),
}, },
"flex volume driver with empty whitelist (only flex volumes volumes are allowed)": { "flex volume driver with empty allowlist (only flex volumes volumes are allowed)": {
pod: flexVolumePod, pod: flexVolumePod,
psp: allowFlexVolumesPSP(true, false), psp: allowFlexVolumesPSP(true, false),
}, },

View File

@ -24,12 +24,12 @@ import (
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
) )
// SafeSysctlWhitelist returns the whitelist of safe sysctls and safe sysctl patterns (ending in *). // SafeSysctlAllowlist returns the allowlist of safe sysctls and safe sysctl patterns (ending in *).
// //
// A sysctl is called safe iff // A sysctl is called safe iff
// - it is namespaced in the container or the pod // - it is namespaced in the container or the pod
// - it is isolated, i.e. has no influence on any other pod on the same node. // - it is isolated, i.e. has no influence on any other pod on the same node.
func SafeSysctlWhitelist() []string { func SafeSysctlAllowlist() []string {
return []string{ return []string{
"kernel.shm_rmid_forced", "kernel.shm_rmid_forced",
"net.ipv4.ip_local_port_range", "net.ipv4.ip_local_port_range",
@ -41,7 +41,7 @@ func SafeSysctlWhitelist() []string {
// mustMatchPatterns implements the SysctlsStrategy interface // mustMatchPatterns implements the SysctlsStrategy interface
type mustMatchPatterns struct { type mustMatchPatterns struct {
safeWhitelist []string safeAllowlist []string
allowedUnsafeSysctls []string allowedUnsafeSysctls []string
forbiddenSysctls []string forbiddenSysctls []string
} }
@ -52,9 +52,9 @@ var (
// NewMustMatchPatterns creates a new mustMatchPatterns strategy that will provide validation. // NewMustMatchPatterns creates a new mustMatchPatterns strategy that will provide validation.
// Passing nil means the default pattern, passing an empty list means to disallow all sysctls. // Passing nil means the default pattern, passing an empty list means to disallow all sysctls.
func NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) SysctlsStrategy { func NewMustMatchPatterns(safeAllowlist, allowedUnsafeSysctls, forbiddenSysctls []string) SysctlsStrategy {
return &mustMatchPatterns{ return &mustMatchPatterns{
safeWhitelist: safeWhitelist, safeAllowlist: safeAllowlist,
allowedUnsafeSysctls: allowedUnsafeSysctls, allowedUnsafeSysctls: allowedUnsafeSysctls,
forbiddenSysctls: forbiddenSysctls, forbiddenSysctls: forbiddenSysctls,
} }
@ -76,7 +76,7 @@ func (s *mustMatchPatterns) isForbidden(sysctlName string) bool {
} }
func (s *mustMatchPatterns) isSafe(sysctlName string) bool { func (s *mustMatchPatterns) isSafe(sysctlName string) bool {
for _, ws := range s.safeWhitelist { for _, ws := range s.safeAllowlist {
if sysctlName == ws { if sysctlName == ws {
return true return true
} }

View File

@ -24,7 +24,7 @@ import (
func TestValidate(t *testing.T) { func TestValidate(t *testing.T) {
tests := map[string]struct { tests := map[string]struct {
whitelist []string allowlist []string
forbiddenSafe []string forbiddenSafe []string
allowedUnsafe []string allowedUnsafe []string
allowed []string allowed []string
@ -32,16 +32,16 @@ func TestValidate(t *testing.T) {
}{ }{
// no container requests // no container requests
"with allow all": { "with allow all": {
whitelist: []string{"foo"}, allowlist: []string{"foo"},
allowed: []string{"foo"}, allowed: []string{"foo"},
}, },
"empty": { "empty": {
whitelist: []string{"foo"}, allowlist: []string{"foo"},
forbiddenSafe: []string{"*"}, forbiddenSafe: []string{"*"},
disallowed: []string{"foo"}, disallowed: []string{"foo"},
}, },
"without wildcard": { "without wildcard": {
whitelist: []string{"a", "a.b"}, allowlist: []string{"a", "a.b"},
allowed: []string{"a", "a.b"}, allowed: []string{"a", "a.b"},
disallowed: []string{"b"}, disallowed: []string{"b"},
}, },
@ -57,7 +57,7 @@ func TestValidate(t *testing.T) {
} }
for k, v := range tests { for k, v := range tests {
strategy := NewMustMatchPatterns(v.whitelist, v.allowedUnsafe, v.forbiddenSafe) strategy := NewMustMatchPatterns(v.allowlist, v.allowedUnsafe, v.forbiddenSafe)
pod := &api.Pod{} pod := &api.Pod{}
errs := strategy.Validate(pod) errs := strategy.Validate(pod)