mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
move sysctl namespace and some funcs to component helpers util
Signed-off-by: Paco Xu <paco.xu@daocloud.io>
This commit is contained in:
parent
4321652d13
commit
11de9543ee
@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
utilsysctl "k8s.io/component-helpers/node/util/sysctl"
|
||||
"k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
policyvalidation "k8s.io/kubernetes/pkg/apis/policy/validation"
|
||||
"k8s.io/kubernetes/pkg/kubelet/lifecycle"
|
||||
@ -33,8 +34,8 @@ const (
|
||||
// checks validity via a sysctl and prefix map, rejecting those which are not known
|
||||
// to be namespaced.
|
||||
type patternAllowlist struct {
|
||||
sysctls map[string]Namespace
|
||||
prefixes map[string]Namespace
|
||||
sysctls map[string]utilsysctl.Namespace
|
||||
prefixes map[string]utilsysctl.Namespace
|
||||
}
|
||||
|
||||
var _ lifecycle.PodAdmitHandler = &patternAllowlist{}
|
||||
@ -42,8 +43,8 @@ var _ lifecycle.PodAdmitHandler = &patternAllowlist{}
|
||||
// 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{},
|
||||
sysctls: map[string]utilsysctl.Namespace{},
|
||||
prefixes: map[string]utilsysctl.Namespace{},
|
||||
}
|
||||
|
||||
for _, s := range patterns {
|
||||
@ -54,17 +55,17 @@ func NewAllowlist(patterns []string) (*patternAllowlist, error) {
|
||||
policyvalidation.SysctlContainSlashPatternFmt,
|
||||
)
|
||||
}
|
||||
s = convertSysctlVariableToDotsSeparator(s)
|
||||
s = utilsysctl.ConvertSysctlVariableToDotsSeparator(s)
|
||||
if strings.HasSuffix(s, "*") {
|
||||
prefix := s[:len(s)-1]
|
||||
ns := NamespacedBy(prefix)
|
||||
if ns == unknownNamespace {
|
||||
ns := utilsysctl.NamespacedBy(prefix)
|
||||
if ns == utilsysctl.UnknownNamespace {
|
||||
return nil, fmt.Errorf("the sysctls %q are not known to be namespaced", s)
|
||||
}
|
||||
w.prefixes[prefix] = ns
|
||||
} else {
|
||||
ns := NamespacedBy(s)
|
||||
if ns == unknownNamespace {
|
||||
ns := utilsysctl.NamespacedBy(s)
|
||||
if ns == utilsysctl.UnknownNamespace {
|
||||
return nil, fmt.Errorf("the sysctl %q are not known to be namespaced", s)
|
||||
}
|
||||
w.sysctls[s] = ns
|
||||
@ -81,23 +82,23 @@ func NewAllowlist(patterns []string) (*patternAllowlist, error) {
|
||||
// respective namespaces with the host. This check is only possible for sysctls on
|
||||
// the static default allowlist, not those on the custom allowlist provided by the admin.
|
||||
func (w *patternAllowlist) validateSysctl(sysctl string, hostNet, hostIPC bool) error {
|
||||
sysctl = convertSysctlVariableToDotsSeparator(sysctl)
|
||||
sysctl = utilsysctl.ConvertSysctlVariableToDotsSeparator(sysctl)
|
||||
nsErrorFmt := "%q not allowed with host %s enabled"
|
||||
if ns, found := w.sysctls[sysctl]; found {
|
||||
if ns == ipcNamespace && hostIPC {
|
||||
if ns == utilsysctl.IpcNamespace && hostIPC {
|
||||
return fmt.Errorf(nsErrorFmt, sysctl, ns)
|
||||
}
|
||||
if ns == netNamespace && hostNet {
|
||||
if ns == utilsysctl.NetNamespace && hostNet {
|
||||
return fmt.Errorf(nsErrorFmt, sysctl, ns)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
for p, ns := range w.prefixes {
|
||||
if strings.HasPrefix(sysctl, p) {
|
||||
if ns == ipcNamespace && hostIPC {
|
||||
if ns == utilsysctl.IpcNamespace && hostIPC {
|
||||
return fmt.Errorf(nsErrorFmt, sysctl, ns)
|
||||
}
|
||||
if ns == netNamespace && hostNet {
|
||||
if ns == utilsysctl.NetNamespace && hostNet {
|
||||
return fmt.Errorf(nsErrorFmt, sysctl, ns)
|
||||
}
|
||||
return nil
|
||||
|
@ -17,39 +17,10 @@ limitations under the License.
|
||||
package sysctl
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
utilsysctl "k8s.io/component-helpers/node/util/sysctl"
|
||||
)
|
||||
|
||||
// convertSysctlVariableToDotsSeparator can return sysctl variables in dots separator format.
|
||||
// The '/' separator is also accepted in place of a '.'.
|
||||
// Convert the sysctl variables to dots separator format for validation.
|
||||
// More info:
|
||||
//
|
||||
// https://man7.org/linux/man-pages/man8/sysctl.8.html
|
||||
// https://man7.org/linux/man-pages/man5/sysctl.d.5.html
|
||||
func convertSysctlVariableToDotsSeparator(val string) string {
|
||||
if val == "" {
|
||||
return val
|
||||
}
|
||||
firstSepIndex := strings.IndexAny(val, "./")
|
||||
if firstSepIndex == -1 || val[firstSepIndex] == '.' {
|
||||
return val
|
||||
}
|
||||
|
||||
f := func(r rune) rune {
|
||||
switch r {
|
||||
case '.':
|
||||
return '/'
|
||||
case '/':
|
||||
return '.'
|
||||
}
|
||||
return r
|
||||
}
|
||||
return strings.Map(f, val)
|
||||
}
|
||||
|
||||
// ConvertPodSysctlsVariableToDotsSeparator converts sysctls variable in the Pod.Spec.SecurityContext.Sysctls slice into a dot as a separator
|
||||
// according to the linux sysctl conversion rules.
|
||||
// see https://man7.org/linux/man-pages/man5/sysctl.d.5.html for more details.
|
||||
@ -58,7 +29,7 @@ func ConvertPodSysctlsVariableToDotsSeparator(securityContext *v1.PodSecurityCon
|
||||
return
|
||||
}
|
||||
for i, sysctl := range securityContext.Sysctls {
|
||||
securityContext.Sysctls[i].Name = convertSysctlVariableToDotsSeparator(sysctl.Name)
|
||||
securityContext.Sysctls[i].Name = utilsysctl.ConvertSysctlVariableToDotsSeparator(sysctl.Name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -24,29 +24,6 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestConvertSysctlVariableToDotsSeparator tests whether the sysctl variable
|
||||
// can be correctly converted to a dot as a separator.
|
||||
func TestConvertSysctlVariableToDotsSeparator(t *testing.T) {
|
||||
type testCase struct {
|
||||
in string
|
||||
out string
|
||||
}
|
||||
valid := []testCase{
|
||||
{in: "kernel.shm_rmid_forced", out: "kernel.shm_rmid_forced"},
|
||||
{in: "kernel/shm_rmid_forced", out: "kernel.shm_rmid_forced"},
|
||||
{in: "net.ipv4.conf.eno2/100.rp_filter", out: "net.ipv4.conf.eno2/100.rp_filter"},
|
||||
{in: "net/ipv4/conf/eno2.100/rp_filter", out: "net.ipv4.conf.eno2/100.rp_filter"},
|
||||
{in: "net/ipv4/ip_local_port_range", out: "net.ipv4.ip_local_port_range"},
|
||||
{in: "kernel/msgmax", out: "kernel.msgmax"},
|
||||
{in: "kernel/sem", out: "kernel.sem"},
|
||||
}
|
||||
|
||||
for _, test := range valid {
|
||||
convertSysctlVal := convertSysctlVariableToDotsSeparator(test.in)
|
||||
assert.Equalf(t, test.out, convertSysctlVal, "The sysctl variable was not converted correctly. got: %s, want: %s", convertSysctlVal, test.out)
|
||||
}
|
||||
}
|
||||
|
||||
// TestConvertPodSysctlsVariableToDotsSeparator tests whether the sysctls variable
|
||||
// can be correctly converted to a dot as a separator.
|
||||
func TestConvertPodSysctlsVariableToDotsSeparator(t *testing.T) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -25,24 +25,24 @@ type Namespace string
|
||||
|
||||
const (
|
||||
// the Linux IPC namespace
|
||||
ipcNamespace = Namespace("ipc")
|
||||
IpcNamespace = Namespace("ipc")
|
||||
|
||||
// the network namespace
|
||||
netNamespace = Namespace("net")
|
||||
NetNamespace = Namespace("net")
|
||||
|
||||
// the zero value if no namespace is known
|
||||
unknownNamespace = Namespace("")
|
||||
UnknownNamespace = Namespace("")
|
||||
)
|
||||
|
||||
var namespaces = map[string]Namespace{
|
||||
"kernel.sem": ipcNamespace,
|
||||
"kernel.sem": IpcNamespace,
|
||||
}
|
||||
|
||||
var prefixNamespaces = map[string]Namespace{
|
||||
"kernel.shm": ipcNamespace,
|
||||
"kernel.msg": ipcNamespace,
|
||||
"fs.mqueue.": ipcNamespace,
|
||||
"net.": netNamespace,
|
||||
"kernel.shm": IpcNamespace,
|
||||
"kernel.msg": IpcNamespace,
|
||||
"fs.mqueue.": IpcNamespace,
|
||||
"net.": NetNamespace,
|
||||
}
|
||||
|
||||
// NamespacedBy returns the namespace of the Linux kernel for a sysctl, or
|
||||
@ -56,5 +56,5 @@ func NamespacedBy(val string) Namespace {
|
||||
return ns
|
||||
}
|
||||
}
|
||||
return unknownNamespace
|
||||
return UnknownNamespace
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -22,10 +22,10 @@ import (
|
||||
|
||||
func TestNamespacedBy(t *testing.T) {
|
||||
tests := map[string]Namespace{
|
||||
"kernel.shm_rmid_forced": ipcNamespace,
|
||||
"net.a.b.c": netNamespace,
|
||||
"fs.mqueue.a.b.c": ipcNamespace,
|
||||
"foo": unknownNamespace,
|
||||
"kernel.shm_rmid_forced": IpcNamespace,
|
||||
"net.a.b.c": NetNamespace,
|
||||
"fs.mqueue.a.b.c": IpcNamespace,
|
||||
"foo": UnknownNamespace,
|
||||
}
|
||||
|
||||
for sysctl, ns := range tests {
|
@ -98,3 +98,31 @@ func (*procSysctl) GetSysctl(sysctl string) (int, error) {
|
||||
func (*procSysctl) SetSysctl(sysctl string, newVal int) error {
|
||||
return os.WriteFile(path.Join(sysctlBase, sysctl), []byte(strconv.Itoa(newVal)), 0640)
|
||||
}
|
||||
|
||||
// ConvertSysctlVariableToDotsSeparator can return sysctl variables in dots separator format.
|
||||
// The '/' separator is also accepted in place of a '.'.
|
||||
// Convert the sysctl variables to dots separator format for validation.
|
||||
// More info:
|
||||
//
|
||||
// https://man7.org/linux/man-pages/man8/sysctl.8.html
|
||||
// https://man7.org/linux/man-pages/man5/sysctl.d.5.html
|
||||
func ConvertSysctlVariableToDotsSeparator(val string) string {
|
||||
if val == "" {
|
||||
return val
|
||||
}
|
||||
firstSepIndex := strings.IndexAny(val, "./")
|
||||
if firstSepIndex == -1 || val[firstSepIndex] == '.' {
|
||||
return val
|
||||
}
|
||||
|
||||
f := func(r rune) rune {
|
||||
switch r {
|
||||
case '.':
|
||||
return '/'
|
||||
case '/':
|
||||
return '.'
|
||||
}
|
||||
return r
|
||||
}
|
||||
return strings.Map(f, val)
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package sysctl
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestConvertSysctlVariableToDotsSeparator tests whether the sysctl variable
|
||||
// can be correctly converted to a dot as a separator.
|
||||
func TestConvertSysctlVariableToDotsSeparator(t *testing.T) {
|
||||
type testCase struct {
|
||||
in string
|
||||
out string
|
||||
}
|
||||
valid := []testCase{
|
||||
{in: "kernel.shm_rmid_forced", out: "kernel.shm_rmid_forced"},
|
||||
{in: "kernel/shm_rmid_forced", out: "kernel.shm_rmid_forced"},
|
||||
{in: "net.ipv4.conf.eno2/100.rp_filter", out: "net.ipv4.conf.eno2/100.rp_filter"},
|
||||
{in: "net/ipv4/conf/eno2.100/rp_filter", out: "net.ipv4.conf.eno2/100.rp_filter"},
|
||||
{in: "net/ipv4/ip_local_port_range", out: "net.ipv4.ip_local_port_range"},
|
||||
{in: "kernel/msgmax", out: "kernel.msgmax"},
|
||||
{in: "kernel/sem", out: "kernel.sem"},
|
||||
}
|
||||
|
||||
for _, test := range valid {
|
||||
convertSysctlVal := ConvertSysctlVariableToDotsSeparator(test.in)
|
||||
assert.Equalf(t, test.out, convertSysctlVal, "The sysctl variable was not converted correctly. got: %s, want: %s", convertSysctlVal, test.out)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user