Merge pull request #77820 from dims/charrywanganthony-pr-71835-delete-kubelet-security-controls

Remove deprecated Kubelet security controls
k3s-v1.15.3
Kubernetes Prow Robot 2019-05-22 13:52:25 -07:00 committed by GitHub
commit 4f33b5f421
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 11 additions and 409 deletions

View File

@ -730,7 +730,6 @@ function construct-common-kubelet-flags {
function construct-linux-kubelet-flags {
local master="$1"
local flags="$(construct-common-kubelet-flags)"
flags+=" --allow-privileged=true"
# Keep in sync with CONTAINERIZED_MOUNTER_HOME in configure-helper.sh
flags+=" --experimental-mounter-path=/home/kubernetes/containerized_mounter/mounter"
flags+=" --experimental-check-node-capabilities-before-mount=true"

View File

@ -107,7 +107,6 @@ function create_cluster {
--address=0.0.0.0 \
--kubeconfig=${KUBELET_KUBECONFIG} \
--pod-manifest-path=/etc/kubernetes/manifests \
--allow-privileged=true \
--cluster-dns=10.0.0.10 \
--cluster-domain=cluster.local \
--v=2"

View File

@ -39,7 +39,6 @@ import (
kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/config/scheme"
kubeletconfigvalidation "k8s.io/kubernetes/pkg/kubelet/apis/config/validation"
"k8s.io/kubernetes/pkg/kubelet/config"
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/master/ports"
utilflag "k8s.io/kubernetes/pkg/util/flag"
utiltaints "k8s.io/kubernetes/pkg/util/taints"
@ -195,19 +194,6 @@ type KubeletFlags struct {
// This flag, if set, instructs the kubelet to keep volumes from terminated pods mounted to the node.
// This can be useful for debugging volume related issues.
KeepTerminatedPodVolumes bool
// allowPrivileged enables containers to request privileged mode.
// Defaults to true.
AllowPrivileged bool
// hostNetworkSources is a comma-separated list of sources from which the
// Kubelet allows pods to use of host network. Defaults to "*". Valid
// options are "file", "http", "api", and "*" (all sources).
HostNetworkSources []string
// hostPIDSources is a comma-separated list of sources from which the
// Kubelet allows pods to use the host pid namespace. Defaults to "*".
HostPIDSources []string
// hostIPCSources is a comma-separated list of sources from which the
// Kubelet allows pods to use the host ipc namespace. Defaults to "*".
HostIPCSources []string
}
// NewKubeletFlags will create a new KubeletFlags with default values
@ -236,11 +222,6 @@ func NewKubeletFlags() *KubeletFlags {
VolumePluginDir: "/usr/libexec/kubernetes/kubelet-plugins/volume/exec/",
RegisterNode: true,
SeccompProfileRoot: filepath.Join(defaultRootDir, "seccomp"),
HostNetworkSources: []string{kubetypes.AllSource},
HostPIDSources: []string{kubetypes.AllSource},
HostIPCSources: []string{kubetypes.AllSource},
// TODO(#58010:v1.13.0): Remove --allow-privileged, it is deprecated
AllowPrivileged: true,
// prior to the introduction of this flag, there was a hardcoded cap of 50 images
NodeStatusMaxImages: 50,
}
@ -443,18 +424,6 @@ func (f *KubeletFlags) AddFlags(mainfs *pflag.FlagSet) {
fs.MarkDeprecated("non-masquerade-cidr", "will be removed in a future version")
fs.BoolVar(&f.KeepTerminatedPodVolumes, "keep-terminated-pod-volumes", f.KeepTerminatedPodVolumes, "Keep terminated pod volumes mounted to the node after the pod terminates. Can be useful for debugging volume related issues.")
fs.MarkDeprecated("keep-terminated-pod-volumes", "will be removed in a future version")
// TODO(#58010:v1.13.0): Remove --allow-privileged, it is deprecated
fs.BoolVar(&f.AllowPrivileged, "allow-privileged", f.AllowPrivileged, "If true, allow containers to request privileged mode. Default: true")
fs.MarkDeprecated("allow-privileged", "will be removed in a future version")
// TODO(#58010:v1.12.0): Remove --host-network-sources, it is deprecated
fs.StringSliceVar(&f.HostNetworkSources, "host-network-sources", f.HostNetworkSources, "Comma-separated list of sources from which the Kubelet allows pods to use of host network.")
fs.MarkDeprecated("host-network-sources", "will be removed in a future version")
// TODO(#58010:v1.12.0): Remove --host-pid-sources, it is deprecated
fs.StringSliceVar(&f.HostPIDSources, "host-pid-sources", f.HostPIDSources, "Comma-separated list of sources from which the Kubelet allows pods to use the host pid namespace.")
fs.MarkDeprecated("host-pid-sources", "will be removed in a future version")
// TODO(#58010:v1.12.0): Remove --host-ipc-sources, it is deprecated
fs.StringSliceVar(&f.HostIPCSources, "host-ipc-sources", f.HostIPCSources, "Comma-separated list of sources from which the Kubelet allows pods to use the host ipc namespace.")
fs.MarkDeprecated("host-ipc-sources", "will be removed in a future version")
}

View File

@ -974,32 +974,9 @@ func RunKubelet(kubeServer *options.KubeletServer, kubeDeps *kubelet.Dependencie
// Setup event recorder if required.
makeEventRecorder(kubeDeps, nodeName)
// TODO(mtaufen): I moved the validation of these fields here, from UnsecuredKubeletConfig,
// so that I could remove the associated fields from KubeletConfiginternal. I would
// prefer this to be done as part of an independent validation step on the
// KubeletConfiguration. But as far as I can tell, we don't have an explicit
// place for validation of the KubeletConfiguration yet.
hostNetworkSources, err := kubetypes.GetValidatedSources(kubeServer.HostNetworkSources)
if err != nil {
return err
}
hostPIDSources, err := kubetypes.GetValidatedSources(kubeServer.HostPIDSources)
if err != nil {
return err
}
hostIPCSources, err := kubetypes.GetValidatedSources(kubeServer.HostIPCSources)
if err != nil {
return err
}
privilegedSources := capabilities.PrivilegedSources{
HostNetworkSources: hostNetworkSources,
HostPIDSources: hostPIDSources,
HostIPCSources: hostIPCSources,
}
capabilities.Setup(kubeServer.AllowPrivileged, privilegedSources, 0)
capabilities.Initialize(capabilities.Capabilities{
AllowPrivileged: true,
})
credentialprovider.SetPreferredDockercfgPath(kubeServer.RootDirectory)
klog.V(2).Infof("Using root directory: %v", kubeServer.RootDirectory)

View File

@ -687,11 +687,6 @@ function start_kubelet {
KUBELET_LOG=${LOG_DIR}/kubelet.log
mkdir -p "${POD_MANIFEST_PATH}" &>/dev/null || sudo mkdir -p "${POD_MANIFEST_PATH}"
priv_arg=""
if [[ -n "${ALLOW_PRIVILEGED}" ]]; then
priv_arg="--allow-privileged=${ALLOW_PRIVILEGED}"
fi
cloud_config_arg=("--cloud-provider=${CLOUD_PROVIDER}" "--cloud-config=${CLOUD_CONFIG}")
if [[ "${EXTERNAL_CLOUD_PROVIDER:-}" == "true" ]]; then
cloud_config_arg=("--cloud-provider=external")
@ -752,7 +747,6 @@ function start_kubelet {
# shellcheck disable=SC2206
all_kubelet_flags=(
${priv_arg:+"$priv_arg"}
"--v=${LOG_LEVEL}"
"--vmodule=${LOG_SPEC}"
"--chaos-chance=${CHAOS_CHANCE}"

View File

@ -1,10 +1,6 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
@ -15,12 +11,6 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/capabilities",
)
go_test(
name = "go_default_test",
srcs = ["capabilities_test.go"],
embed = [":go_default_library"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
@ -33,3 +23,9 @@ filegroup(
srcs = [":package-srcs"],
tags = ["automanaged"],
)
go_test(
name = "go_default_test",
srcs = ["capabilities_test.go"],
embed = [":go_default_library"],
)

View File

@ -61,10 +61,9 @@ func Initialize(c Capabilities) {
}
// Setup the capability set. It wraps Initialize for improving usability.
func Setup(allowPrivileged bool, privilegedSources PrivilegedSources, perConnectionBytesPerSec int64) {
func Setup(allowPrivileged bool, perConnectionBytesPerSec int64) {
Initialize(Capabilities{
AllowPrivileged: allowPrivileged,
PrivilegedSources: privilegedSources,
PerConnectionBandwidthLimitBytesPerSec: perConnectionBytesPerSec,
})
}

View File

@ -38,7 +38,6 @@ go_library(
"//pkg/apis/core/v1:go_default_library",
"//pkg/apis/core/v1/helper:go_default_library",
"//pkg/apis/core/v1/helper/qos:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/features:go_default_library",
"//pkg/fieldpath:go_default_library",
"//pkg/kubelet/apis:go_default_library",
@ -99,7 +98,6 @@ go_library(
"//pkg/scheduler/api:go_default_library",
"//pkg/security/apparmor:go_default_library",
"//pkg/security/podsecuritypolicy/sysctl:go_default_library",
"//pkg/securitycontext:go_default_library",
"//pkg/util/dbus:go_default_library",
"//pkg/util/iptables:go_default_library",
"//pkg/util/mount:go_default_library",
@ -176,7 +174,6 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core/install:go_default_library",
"//pkg/capabilities:go_default_library",
"//pkg/features:go_default_library",
"//pkg/kubelet/apis:go_default_library",
"//pkg/kubelet/cadvisor/testing:go_default_library",

View File

@ -1795,15 +1795,6 @@ func (kl *Kubelet) canRunPod(pod *v1.Pod) lifecycle.PodAdmitResult {
}
}
// TODO: Refactor as a soft admit handler.
if err := canRunPod(pod); err != nil {
return lifecycle.PodAdmitResult{
Admit: false,
Reason: "Forbidden",
Message: err.Error(),
}
}
return lifecycle.PodAdmitResult{Admit: true}
}

View File

@ -41,7 +41,6 @@ import (
"k8s.io/client-go/util/flowcontrol"
"k8s.io/component-base/featuregate"
featuregatetesting "k8s.io/component-base/featuregate/testing"
"k8s.io/kubernetes/pkg/capabilities"
cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
"k8s.io/kubernetes/pkg/kubelet/cm"
"k8s.io/kubernetes/pkg/kubelet/config"
@ -1098,230 +1097,12 @@ func TestGetContainerInfoForMirrorPods(t *testing.T) {
require.NotNil(t, stats)
}
func TestHostNetworkAllowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
PrivilegedSources: capabilities.PrivilegedSources{
HostNetworkSources: []string{kubetypes.ApiserverSource, kubetypes.FileSource},
},
})
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo"},
},
HostNetwork: true,
})
pod.Annotations[kubetypes.ConfigSourceAnnotationKey] = kubetypes.FileSource
kubelet.podManager.SetPods([]*v1.Pod{pod})
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.NoError(t, err, "expected pod infra creation to succeed")
}
func TestHostNetworkDisallowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
PrivilegedSources: capabilities.PrivilegedSources{
HostNetworkSources: []string{},
},
})
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo"},
},
HostNetwork: true,
})
pod.Annotations[kubetypes.ConfigSourceAnnotationKey] = kubetypes.FileSource
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.Error(t, err, "expected pod infra creation to fail")
}
func TestHostPIDAllowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
PrivilegedSources: capabilities.PrivilegedSources{
HostPIDSources: []string{kubetypes.ApiserverSource, kubetypes.FileSource},
},
})
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo"},
},
HostPID: true,
})
pod.Annotations[kubetypes.ConfigSourceAnnotationKey] = kubetypes.FileSource
kubelet.podManager.SetPods([]*v1.Pod{pod})
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.NoError(t, err, "expected pod infra creation to succeed")
}
func TestHostPIDDisallowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
PrivilegedSources: capabilities.PrivilegedSources{
HostPIDSources: []string{},
},
})
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo"},
},
HostPID: true,
})
pod.Annotations[kubetypes.ConfigSourceAnnotationKey] = kubetypes.FileSource
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.Error(t, err, "expected pod infra creation to fail")
}
func TestHostIPCAllowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
PrivilegedSources: capabilities.PrivilegedSources{
HostIPCSources: []string{kubetypes.ApiserverSource, kubetypes.FileSource},
},
})
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo"},
},
HostIPC: true,
})
pod.Annotations[kubetypes.ConfigSourceAnnotationKey] = kubetypes.FileSource
kubelet.podManager.SetPods([]*v1.Pod{pod})
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.NoError(t, err, "expected pod infra creation to succeed")
}
func TestHostIPCDisallowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
PrivilegedSources: capabilities.PrivilegedSources{
HostIPCSources: []string{},
},
})
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo"},
},
HostIPC: true,
})
pod.Annotations[kubetypes.ConfigSourceAnnotationKey] = kubetypes.FileSource
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.Error(t, err, "expected pod infra creation to fail")
}
func TestPrivilegeContainerAllowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
AllowPrivileged: true,
})
privileged := true
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo", SecurityContext: &v1.SecurityContext{Privileged: &privileged}},
},
})
kubelet.podManager.SetPods([]*v1.Pod{pod})
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.NoError(t, err, "expected pod infra creation to succeed")
}
func TestPrivilegedContainerDisallowed(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
capabilities.SetForTests(capabilities.Capabilities{
AllowPrivileged: false,
})
privileged := true
pod := podWithUIDNameNsSpec("12345678", "foo", "new", v1.PodSpec{
Containers: []v1.Container{
{Name: "foo", SecurityContext: &v1.SecurityContext{Privileged: &privileged}},
},
})
err := kubelet.syncPod(syncPodOptions{
pod: pod,
podStatus: &kubecontainer.PodStatus{},
updateType: kubetypes.SyncPodUpdate,
})
assert.Error(t, err, "expected pod infra creation to fail")
}
func TestNetworkErrorsWithoutHostNetwork(t *testing.T) {
testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */)
defer testKubelet.Cleanup()
kubelet := testKubelet.kubelet
kubelet.runtimeState.setNetworkState(fmt.Errorf("simulated network error"))
capabilities.SetForTests(capabilities.Capabilities{
PrivilegedSources: capabilities.PrivilegedSources{
HostNetworkSources: []string{kubetypes.ApiserverSource, kubetypes.FileSource},
},
})
pod := podWithUIDNameNsSpec("12345678", "hostnetwork", "new", v1.PodSpec{
HostNetwork: false,

View File

@ -17,105 +17,9 @@ limitations under the License.
package kubelet
import (
"fmt"
"os"
"k8s.io/api/core/v1"
"k8s.io/kubernetes/pkg/capabilities"
kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
"k8s.io/kubernetes/pkg/securitycontext"
)
// Check whether we have the capabilities to run the specified pod.
func canRunPod(pod *v1.Pod) error {
if !capabilities.Get().AllowPrivileged {
for _, container := range pod.Spec.Containers {
if securitycontext.HasPrivilegedRequest(&container) {
return fmt.Errorf("pod with UID %q specified privileged container, but is disallowed", pod.UID)
}
}
for _, container := range pod.Spec.InitContainers {
if securitycontext.HasPrivilegedRequest(&container) {
return fmt.Errorf("pod with UID %q specified privileged init container, but is disallowed", pod.UID)
}
}
}
if pod.Spec.HostNetwork {
allowed, err := allowHostNetwork(pod)
if err != nil {
return err
}
if !allowed {
return fmt.Errorf("pod with UID %q specified host networking, but is disallowed", pod.UID)
}
}
if pod.Spec.HostPID {
allowed, err := allowHostPID(pod)
if err != nil {
return err
}
if !allowed {
return fmt.Errorf("pod with UID %q specified host PID, but is disallowed", pod.UID)
}
}
if pod.Spec.HostIPC {
allowed, err := allowHostIPC(pod)
if err != nil {
return err
}
if !allowed {
return fmt.Errorf("pod with UID %q specified host ipc, but is disallowed", pod.UID)
}
}
return nil
}
// Determined whether the specified pod is allowed to use host networking
func allowHostNetwork(pod *v1.Pod) (bool, error) {
podSource, err := kubetypes.GetPodSource(pod)
if err != nil {
return false, err
}
for _, source := range capabilities.Get().PrivilegedSources.HostNetworkSources {
if source == podSource {
return true, nil
}
}
return false, nil
}
// Determined whether the specified pod is allowed to use host PID
func allowHostPID(pod *v1.Pod) (bool, error) {
podSource, err := kubetypes.GetPodSource(pod)
if err != nil {
return false, err
}
for _, source := range capabilities.Get().PrivilegedSources.HostPIDSources {
if source == podSource {
return true, nil
}
}
return false, nil
}
// Determined whether the specified pod is allowed to use host ipc
func allowHostIPC(pod *v1.Pod) (bool, error) {
podSource, err := kubetypes.GetPodSource(pod)
if err != nil {
return false, err
}
for _, source := range capabilities.Get().PrivilegedSources.HostIPCSources {
if source == podSource {
return true, nil
}
}
return false, nil
}
// dirExists returns true if the path exists and represents a directory.
func dirExists(path string) bool {
s, err := os.Stat(path)

View File

@ -176,7 +176,6 @@ if [ ! -z $pid ]; then
fi
volume_stats_agg_period=10s
allow_privileged=true
serialize_image_pulls=false
config_dir=`mktemp -d`
file_check_frequency=10s
@ -184,7 +183,6 @@ pod_cidr=10.100.0.0/24
log_level=4
start_kubelet --kubeconfig ${KUBELET_KUBECONFIG} \
--volume-stats-agg-period $volume_stats_agg_period \
--allow-privileged=$allow_privileged \
--serialize-image-pulls=$serialize_image_pulls \
--pod-manifest-path $config_dir \
--file-check-frequency $file_check_frequency \

View File

@ -260,7 +260,6 @@ func (e *E2EServices) startKubelet() (*server, error) {
"--kubeconfig", kubeconfigPath,
"--root-dir", KubeletRootDirectory,
"--v", LogVerbosityLevel, "--logtostderr",
"--allow-privileged=true",
)
// Apply test framework feature gates by default. This could also be overridden

View File

@ -257,7 +257,6 @@ function load-docker-images {
# Computes command line arguments to be passed to kubelet.
function compute-kubelet-params {
local params="${KUBELET_TEST_ARGS:-}"
params+=" --allow-privileged=true"
params+=" --cgroup-root=/"
params+=" --cloud-provider=gce"
params+=" --pod-manifest-path=/etc/kubernetes/manifests"