...

Source file src/k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod/utils_linux_test.go

Documentation: k8s.io/kubernetes/cmd/kubeadm/app/util/staticpod

     1  //go:build linux
     2  // +build linux
     3  
     4  /*
     5  Copyright 2021 The Kubernetes Authors.
     6  
     7  Licensed under the Apache License, Version 2.0 (the "License");
     8  you may not use this file except in compliance with the License.
     9  You may obtain a copy of the License at
    10  
    11      http://www.apache.org/licenses/LICENSE-2.0
    12  
    13  Unless required by applicable law or agreed to in writing, software
    14  distributed under the License is distributed on an "AS IS" BASIS,
    15  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16  See the License for the specific language governing permissions and
    17  limitations under the License.
    18  */
    19  
    20  package staticpod
    21  
    22  import (
    23  	"path/filepath"
    24  	"reflect"
    25  	"testing"
    26  
    27  	v1 "k8s.io/api/core/v1"
    28  	"k8s.io/utils/ptr"
    29  
    30  	"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
    31  	kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
    32  )
    33  
    34  type ownerAndPermissions struct {
    35  	uid         int64
    36  	gid         int64
    37  	permissions uint32
    38  }
    39  
    40  func verifyPodSecurityContext(t *testing.T, pod *v1.Pod, wantRunAsUser, wantRunAsGroup int64, wantSupGroup []int64) {
    41  	t.Helper()
    42  	wantPodSecurityContext := &v1.PodSecurityContext{
    43  		RunAsUser:          ptr.To(wantRunAsUser),
    44  		RunAsGroup:         ptr.To(wantRunAsGroup),
    45  		SupplementalGroups: wantSupGroup,
    46  		SeccompProfile: &v1.SeccompProfile{
    47  			Type: v1.SeccompProfileTypeRuntimeDefault,
    48  		},
    49  	}
    50  	if !reflect.DeepEqual(wantPodSecurityContext, pod.Spec.SecurityContext) {
    51  		t.Errorf("unexpected diff in PodSecurityContext,  want: %+v, got: %+v", wantPodSecurityContext, pod.Spec.SecurityContext)
    52  	}
    53  }
    54  
    55  func verifyContainerSecurityContext(t *testing.T, container v1.Container, addCaps, dropCaps []v1.Capability, allowPrivielege *bool) {
    56  	t.Helper()
    57  	wantContainerSecurityContext := &v1.SecurityContext{
    58  		AllowPrivilegeEscalation: allowPrivielege,
    59  		Capabilities: &v1.Capabilities{
    60  			Add:  addCaps,
    61  			Drop: dropCaps,
    62  		},
    63  	}
    64  	if !reflect.DeepEqual(wantContainerSecurityContext, container.SecurityContext) {
    65  		t.Errorf("unexpected diff in container SecurityContext, want: %+v, got: %+v", wantContainerSecurityContext, container.SecurityContext)
    66  	}
    67  }
    68  
    69  func verifyFilePermissions(t *testing.T, updatedFiles, wantFiles map[string]ownerAndPermissions) {
    70  	t.Helper()
    71  	if !reflect.DeepEqual(updatedFiles, wantFiles) {
    72  		t.Errorf("unexpected diff in file owners and permissions want: %+v, got: %+v", wantFiles, updatedFiles)
    73  	}
    74  }
    75  
    76  func TestRunKubeAPIServerAsNonRoot(t *testing.T) {
    77  	cfg := &kubeadm.ClusterConfiguration{}
    78  	pod := ComponentPod(v1.Container{Name: "kube-apiserver"}, nil, nil)
    79  	var runAsUser, runAsGroup, supGroup int64 = 1000, 1001, 1002
    80  	updatedFiles := map[string]ownerAndPermissions{}
    81  	if err := runKubeAPIServerAsNonRoot(&pod, &runAsUser, &runAsGroup, &supGroup, func(path string, uid, gid int64, perms uint32) error {
    82  		updatedFiles[path] = ownerAndPermissions{uid: uid, gid: gid, permissions: perms}
    83  		return nil
    84  	}, cfg); err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	verifyPodSecurityContext(t, &pod, runAsUser, runAsGroup, []int64{supGroup})
    88  	verifyContainerSecurityContext(t, pod.Spec.Containers[0], []v1.Capability{"NET_BIND_SERVICE"}, []v1.Capability{"ALL"}, nil)
    89  	wantUpdateFiles := map[string]ownerAndPermissions{
    90  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName):   {uid: runAsUser, gid: runAsGroup, permissions: 0600},
    91  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName):  {uid: 0, gid: supGroup, permissions: 0640},
    92  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKeyName):              {uid: runAsUser, gid: runAsGroup, permissions: 0600},
    93  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKubeletClientKeyName): {uid: runAsUser, gid: runAsGroup, permissions: 0600},
    94  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyClientKeyName):       {uid: runAsUser, gid: runAsGroup, permissions: 0600},
    95  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.APIServerEtcdClientKeyName):    {uid: runAsUser, gid: runAsGroup, permissions: 0600},
    96  	}
    97  	verifyFilePermissions(t, updatedFiles, wantUpdateFiles)
    98  }
    99  
   100  func TestRunKubeControllerManagerAsNonRoot(t *testing.T) {
   101  	cfg := &kubeadm.ClusterConfiguration{}
   102  	pod := ComponentPod(v1.Container{Name: "kube-controller-manager"}, nil, nil)
   103  	var runAsUser, runAsGroup, supGroup int64 = 1000, 1001, 1002
   104  	updatedFiles := map[string]ownerAndPermissions{}
   105  	if err := runKubeControllerManagerAsNonRoot(&pod, &runAsUser, &runAsGroup, &supGroup, func(path string, uid, gid int64, perms uint32) error {
   106  		updatedFiles[path] = ownerAndPermissions{uid: uid, gid: gid, permissions: perms}
   107  		return nil
   108  	}, cfg); err != nil {
   109  		t.Fatal(err)
   110  	}
   111  	verifyPodSecurityContext(t, &pod, runAsUser, runAsGroup, []int64{supGroup})
   112  	verifyContainerSecurityContext(t, pod.Spec.Containers[0], nil, []v1.Capability{"ALL"}, ptr.To(false))
   113  	wantUpdateFiles := map[string]ownerAndPermissions{
   114  		filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName): {uid: runAsUser, gid: runAsGroup, permissions: 0600},
   115  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName):                   {uid: 0, gid: supGroup, permissions: 0640},
   116  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName):                                      {uid: runAsUser, gid: runAsGroup, permissions: 0600},
   117  	}
   118  	verifyFilePermissions(t, updatedFiles, wantUpdateFiles)
   119  }
   120  
   121  func TestRunKubeSchedulerAsNonRoot(t *testing.T) {
   122  	pod := ComponentPod(v1.Container{Name: "kube-scheduler"}, nil, nil)
   123  	var runAsUser, runAsGroup int64 = 1000, 1001
   124  	updatedFiles := map[string]ownerAndPermissions{}
   125  	if err := runKubeSchedulerAsNonRoot(&pod, &runAsUser, &runAsGroup, func(path string, uid, gid int64, perms uint32) error {
   126  		updatedFiles[path] = ownerAndPermissions{uid: uid, gid: gid, permissions: perms}
   127  		return nil
   128  	}); err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	verifyPodSecurityContext(t, &pod, runAsUser, runAsGroup, nil)
   132  	verifyContainerSecurityContext(t, pod.Spec.Containers[0], nil, []v1.Capability{"ALL"}, ptr.To(false))
   133  	wantUpdateFiles := map[string]ownerAndPermissions{
   134  		filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.SchedulerKubeConfigFileName): {uid: runAsUser, gid: runAsGroup, permissions: 0600},
   135  	}
   136  	verifyFilePermissions(t, updatedFiles, wantUpdateFiles)
   137  }
   138  
   139  func TestRunEtcdAsNonRoot(t *testing.T) {
   140  	cfg := &kubeadm.ClusterConfiguration{
   141  		Etcd: kubeadm.Etcd{
   142  			Local: &kubeadm.LocalEtcd{
   143  				DataDir: "/var/lib/etcd/data",
   144  			},
   145  		},
   146  	}
   147  	pod := ComponentPod(v1.Container{Name: "etcd"}, nil, nil)
   148  	var runAsUser, runAsGroup int64 = 1000, 1001
   149  	updatedFiles := map[string]ownerAndPermissions{}
   150  	if err := runEtcdAsNonRoot(&pod, &runAsUser, &runAsGroup, func(path string, uid, gid int64, perms uint32) error {
   151  		updatedFiles[path] = ownerAndPermissions{uid: uid, gid: gid, permissions: perms}
   152  		return nil
   153  	},
   154  		func(path string, uid, gid int64) error {
   155  			updatedFiles[path] = ownerAndPermissions{uid: uid, gid: gid, permissions: 0700}
   156  			return nil
   157  		}, cfg); err != nil {
   158  		t.Fatal(err)
   159  	}
   160  	verifyPodSecurityContext(t, &pod, runAsUser, runAsGroup, nil)
   161  	verifyContainerSecurityContext(t, pod.Spec.Containers[0], nil, []v1.Capability{"ALL"}, ptr.To(false))
   162  	wantUpdateFiles := map[string]ownerAndPermissions{
   163  		cfg.Etcd.Local.DataDir: {uid: runAsUser, gid: runAsGroup, permissions: 0700},
   164  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdServerKeyName): {uid: runAsUser, gid: runAsGroup, permissions: 0600},
   165  		filepath.Join(cfg.CertificatesDir, kubeadmconstants.EtcdPeerKeyName):   {uid: runAsUser, gid: runAsGroup, permissions: 0600},
   166  	}
   167  	verifyFilePermissions(t, updatedFiles, wantUpdateFiles)
   168  }
   169  

View as plain text