mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
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:
parent
9c5cefb230
commit
ff165c8823
@ -340,7 +340,7 @@ type KubeletConfiguration struct {
|
||||
ContainerLogMaxFiles int32
|
||||
// ConfigMapAndSecretChangeDetectionStrategy is a mode in which config map and secret managers are running.
|
||||
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.*.
|
||||
// These sysctls are namespaced but not allowed by default. For example: "kernel.msg*,net.ipv4.route.min_pmtu"
|
||||
// +optional
|
||||
|
@ -279,16 +279,16 @@ func (m *cgroupManagerImpl) Exists(name CgroupName) bool {
|
||||
// scoped to the set control groups it understands. this is being discussed
|
||||
// in https://github.com/opencontainers/runc/issues/1440
|
||||
// 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 {
|
||||
whitelistControllers.Insert("hugetlb")
|
||||
allowlistControllers.Insert("hugetlb")
|
||||
}
|
||||
var missingPaths []string
|
||||
// If even one cgroup path doesn't exist, then the cgroup doesn't exist.
|
||||
for controller, path := range cgroupPaths {
|
||||
// ignore mounts we don't care about
|
||||
if !whitelistControllers.Has(controller) {
|
||||
if !allowlistControllers.Has(controller) {
|
||||
continue
|
||||
}
|
||||
if !libcontainercgroups.PathExists(path) {
|
||||
|
@ -112,7 +112,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/sliceutils"
|
||||
"k8s.io/kubernetes/pkg/kubelet/volumemanager"
|
||||
"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/selinux"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
@ -820,14 +820,14 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
|
||||
klet.evictionManager = evictionManager
|
||||
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.
|
||||
safeAndUnsafeSysctls := append(sysctlwhitelist.SafeSysctlWhitelist(), allowedUnsafeSysctls...)
|
||||
sysctlsWhitelist, err := sysctl.NewWhitelist(safeAndUnsafeSysctls)
|
||||
safeAndUnsafeSysctls := append(sysctlallowlist.SafeSysctlAllowlist(), allowedUnsafeSysctls...)
|
||||
sysctlsAllowlist, err := sysctl.NewAllowlist(safeAndUnsafeSysctls)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klet.admitHandlers.AddPodAdmitHandler(sysctlsWhitelist)
|
||||
klet.admitHandlers.AddPodAdmitHandler(sysctlsAllowlist)
|
||||
|
||||
// enable active deadline handler
|
||||
activeDeadlineHandler, err := newActiveDeadlineHandler(klet.statusManager, kubeDeps.Recorder, klet.clock)
|
||||
|
@ -1791,7 +1791,7 @@ func (kl *Kubelet) convertToAPIContainerStatuses(pod *v1.Pod, podStatus *kubecon
|
||||
|
||||
// ServeLogs returns logs of current machine.
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -30,19 +30,19 @@ const (
|
||||
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
|
||||
// to be namespaced.
|
||||
type patternWhitelist struct {
|
||||
type patternAllowlist struct {
|
||||
sysctls 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 *).
|
||||
func NewWhitelist(patterns []string) (*patternWhitelist, error) {
|
||||
w := &patternWhitelist{
|
||||
// NewAllowlist creates a new Allowlist from a list of sysctls and sysctl pattern (ending in *).
|
||||
func NewAllowlist(patterns []string) (*patternAllowlist, error) {
|
||||
w := &patternAllowlist{
|
||||
sysctls: map[string]Namespace{},
|
||||
prefixes: map[string]Namespace{},
|
||||
}
|
||||
@ -73,14 +73,14 @@ func NewWhitelist(patterns []string) (*patternWhitelist, error) {
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// validateSysctl checks that a sysctl is whitelisted because it is known
|
||||
// to be namespaced by the Linux kernel. Note that being whitelisted is required, but not
|
||||
// validateSysctl checks that a sysctl is allowlisted because it is known
|
||||
// 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.
|
||||
//
|
||||
// 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
|
||||
// the static default whitelist, not those on the custom whitelist provided by the admin.
|
||||
func (w *patternWhitelist) validateSysctl(sysctl string, hostNet, hostIPC bool) error {
|
||||
// the static default allowlist, not those on the custom allowlist provided by the admin.
|
||||
func (w *patternAllowlist) validateSysctl(sysctl string, hostNet, hostIPC bool) error {
|
||||
nsErrorFmt := "%q not allowed with host %s enabled"
|
||||
if ns, found := w.sysctls[sysctl]; found {
|
||||
if ns == ipcNamespace && hostIPC {
|
||||
@ -102,12 +102,12 @@ func (w *patternWhitelist) validateSysctl(sysctl string, hostNet, hostIPC bool)
|
||||
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
|
||||
// are valid according to the whitelist.
|
||||
func (w *patternWhitelist) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult {
|
||||
// are valid according to the allowlist.
|
||||
func (w *patternAllowlist) Admit(attrs *lifecycle.PodAdmitAttributes) lifecycle.PodAdmitResult {
|
||||
pod := attrs.Pod
|
||||
if pod.Spec.SecurityContext == nil || len(pod.Spec.SecurityContext.Sysctls) == 0 {
|
||||
return lifecycle.PodAdmitResult{
|
@ -22,7 +22,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/security/podsecuritypolicy/sysctl"
|
||||
)
|
||||
|
||||
func TestNewWhitelist(t *testing.T) {
|
||||
func TestNewAllowlist(t *testing.T) {
|
||||
type Test struct {
|
||||
sysctls []string
|
||||
err bool
|
||||
@ -35,16 +35,16 @@ func TestNewWhitelist(t *testing.T) {
|
||||
{sysctls: []string{"net.*.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 {
|
||||
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 {
|
||||
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 {
|
||||
sysctl string
|
||||
hostNet, hostIPC bool
|
||||
@ -65,14 +65,14 @@ func TestWhitelist(t *testing.T) {
|
||||
{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 {
|
||||
t.Fatalf("failed to create whitelist: %v", err)
|
||||
t.Fatalf("failed to create allowlist: %v", err)
|
||||
}
|
||||
|
||||
for _, test := range valid {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ func (f *simpleStrategyFactory) CreateStrategies(psp *policy.PodSecurityPolicy,
|
||||
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 {
|
||||
return nil, errors.NewAggregate(errs)
|
||||
@ -191,6 +191,6 @@ func createCapabilitiesStrategy(defaultAddCaps, requiredDropCaps, allowedCaps []
|
||||
}
|
||||
|
||||
// createSysctlsStrategy creates a new sysctls strategy.
|
||||
func createSysctlsStrategy(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) sysctl.SysctlsStrategy {
|
||||
return sysctl.NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls)
|
||||
func createSysctlsStrategy(safeAllowlist, allowedUnsafeSysctls, forbiddenSysctls []string) sysctl.SysctlsStrategy {
|
||||
return sysctl.NewMustMatchPatterns(safeAllowlist, allowedUnsafeSysctls, forbiddenSysctls)
|
||||
}
|
||||
|
@ -1006,19 +1006,19 @@ func TestValidatePodSuccess(t *testing.T) {
|
||||
pod: seccompPod,
|
||||
psp: seccompPSP,
|
||||
},
|
||||
"flex volume driver in a whitelist (all volumes are allowed)": {
|
||||
"flex volume driver in a allowlist (all volumes are allowed)": {
|
||||
pod: flexVolumePod,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
psp: allowFlexVolumesPSP(true, false),
|
||||
},
|
||||
|
@ -24,12 +24,12 @@ import (
|
||||
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
|
||||
// - 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.
|
||||
func SafeSysctlWhitelist() []string {
|
||||
func SafeSysctlAllowlist() []string {
|
||||
return []string{
|
||||
"kernel.shm_rmid_forced",
|
||||
"net.ipv4.ip_local_port_range",
|
||||
@ -41,7 +41,7 @@ func SafeSysctlWhitelist() []string {
|
||||
|
||||
// mustMatchPatterns implements the SysctlsStrategy interface
|
||||
type mustMatchPatterns struct {
|
||||
safeWhitelist []string
|
||||
safeAllowlist []string
|
||||
allowedUnsafeSysctls []string
|
||||
forbiddenSysctls []string
|
||||
}
|
||||
@ -52,9 +52,9 @@ var (
|
||||
|
||||
// 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.
|
||||
func NewMustMatchPatterns(safeWhitelist, allowedUnsafeSysctls, forbiddenSysctls []string) SysctlsStrategy {
|
||||
func NewMustMatchPatterns(safeAllowlist, allowedUnsafeSysctls, forbiddenSysctls []string) SysctlsStrategy {
|
||||
return &mustMatchPatterns{
|
||||
safeWhitelist: safeWhitelist,
|
||||
safeAllowlist: safeAllowlist,
|
||||
allowedUnsafeSysctls: allowedUnsafeSysctls,
|
||||
forbiddenSysctls: forbiddenSysctls,
|
||||
}
|
||||
@ -76,7 +76,7 @@ func (s *mustMatchPatterns) isForbidden(sysctlName string) bool {
|
||||
}
|
||||
|
||||
func (s *mustMatchPatterns) isSafe(sysctlName string) bool {
|
||||
for _, ws := range s.safeWhitelist {
|
||||
for _, ws := range s.safeAllowlist {
|
||||
if sysctlName == ws {
|
||||
return true
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ import (
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
tests := map[string]struct {
|
||||
whitelist []string
|
||||
allowlist []string
|
||||
forbiddenSafe []string
|
||||
allowedUnsafe []string
|
||||
allowed []string
|
||||
@ -32,16 +32,16 @@ func TestValidate(t *testing.T) {
|
||||
}{
|
||||
// no container requests
|
||||
"with allow all": {
|
||||
whitelist: []string{"foo"},
|
||||
allowlist: []string{"foo"},
|
||||
allowed: []string{"foo"},
|
||||
},
|
||||
"empty": {
|
||||
whitelist: []string{"foo"},
|
||||
allowlist: []string{"foo"},
|
||||
forbiddenSafe: []string{"*"},
|
||||
disallowed: []string{"foo"},
|
||||
},
|
||||
"without wildcard": {
|
||||
whitelist: []string{"a", "a.b"},
|
||||
allowlist: []string{"a", "a.b"},
|
||||
allowed: []string{"a", "a.b"},
|
||||
disallowed: []string{"b"},
|
||||
},
|
||||
@ -57,7 +57,7 @@ func TestValidate(t *testing.T) {
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
strategy := NewMustMatchPatterns(v.whitelist, v.allowedUnsafe, v.forbiddenSafe)
|
||||
strategy := NewMustMatchPatterns(v.allowlist, v.allowedUnsafe, v.forbiddenSafe)
|
||||
|
||||
pod := &api.Pod{}
|
||||
errs := strategy.Validate(pod)
|
||||
|
Loading…
Reference in New Issue
Block a user