这是关于如何加固kubernetes集群安全的文章。在测试环境下使用默认的users和service accounts的默认受权建立pods并无问题,可是在生产环境下,这可能会致使不可预料的灾难。Kubernetes提供pod security policy用来限制users和service account的权限。nginx
在minikube建立的集群中实践pod security policy前,在这里我将作一些理论基础的介绍。api
读者在实践pod security policy以前必须先要对下面这些名词的概念有充分的理解:数组
Pod Security Policies(Adminssion Controller)授予users和service accounts建立或更新pods使用资源的权限。这是一种集群级别的资源类型,用来限制pod对敏感资源的使用。安全
Addmission controller会拦截发往Kubernetes API Server调用资源的请求,验证请求调用的users和service accout是否已经受权和认证使用被调用的资源对象。例如:Admission controller会验证请求者是否拥有使用hostNetwork等kubernetes资源的权限。bash
对受权资源使用权限的规则定义在YAML文件中。app
规则有两种:一种是限制(restrictive)使用资源的规则,另外一种是容许(permission)使用资源的规则。ide
Pod Security Policy应该遵循如下的规范:测试
在这部分中咱们将开始在集群中实践 pod security policy。ui
PSP(Pod Security Policy) 在默认状况下并不会开启。经过将PodSecurityPolicy关键词添加到 --enbale-admission-plugins 配置数组后,能够开启PSP权限认证功能。spa
Example
--enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,PodSecurityPolicy
复制代码
注意:开启PodSecurityPolicy功能后,即便没有使用任何安全策略,都会使得建立pods(包括调度任务从新建立pods)失败
经过下面的deployment yaml文件测试在没有PSP策略的状况下是否能够建立pod:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.4
复制代码
使用下面的命令建立deployment资源:
sudo kubectl apply -f nginx-deployment.yaml
复制代码
使用下面的命令检查pod是否建立:
kubectl get pods,replicasets,deployments
复制代码
经过上图可见deployments和relicaset正在运行,因为缺乏PSP policy,集群并无建立相应的pods。
下面将建立两个policies,
下面是典型的限制资源使用的restrictive policy:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restrictive
spec:
privileged: false
hostNetwork: false
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
hostPID: false
hostIPC: false
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- 'configMap'
- 'downwardAPI'
- 'emptyDir'
- 'persistentVolumeClaim'
- 'secret'
- 'projected'
allowedCapabilities:
- '*'
复制代码
下面是容许使用资源的permissive policy,多条permissive policy规则被用来设置相应user或者sevice account使用相关类型的资源。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: permissive
spec:
privileged: true
hostNetwork: true
hostIPC: true
hostPID: true
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
hostPorts:
- min: 0
max: 65535
volumes:
- '*'
复制代码
上面两种poicies可使用下面的命令建立对应的PSP资源:
kubectl apply -f default-restrict-psp.yaml
kubectl apply -f permissive-psp.yaml
复制代码
核对psp是否建立成功与否:
sudo kubectl get psp
复制代码
下面将经过cluster role和cluster role binding在集群中使用刚才定义的安全策略(Pod Security Policy)。
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: psp-restrictive
rules:
- apiGroups:
- extensions
resources:
- podsecuritypolicies
resourceNames:
- restrictive
verbs:
- use
复制代码
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: psp-permissive
rules:
- apiGroups:
- extensions
resources:
- podsecuritypolicies
resourceNames:
- permissive
verbs:
- use
复制代码
经过下面命令建立相应的cluster role资源:
kubectl apply -f psp-restrictive-cluster-roleyaml
kubectl apply -f psp-permissive-cluster-roleyaml
复制代码
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: psp-default
subjects:
- kind: Group
name: system:serviceaccounts
namespace: kube-system
roleRef:
kind: ClusterRole
name: psp-restrictive
apiGroup: rbac.authorization.k8s.io
复制代码
上面的role binding会将restrictive cluster role绑定到全部的system service account。
使用下面的命令生成role binding资源:
kubectl apply -f psp-restrictive-cluster-role-binding.yaml
复制代码
已经定义了restrictive policy而且将对应的psp绑定到对应的service account,我将经过从新生成开篇的deployment资源来验证pods是否能够建立。
首先,删除已经存在的deployment资源。
kubectl delete deploy nginx-deployment
kubectl get po,rs,deploy
复制代码
从新建立deployment:
kubectl apply -f nginx-deployment.yaml
kubectl get po,rs,deploy
复制代码
注意:经过图可见在policies建立后,能够建立pod资源。
在这部分,我将在deployment中使用已经在restrictive policy中禁止的“hostNetwork”。
首先,清楚前面建立的deployment资源。
kubectl delete deploy ninx-deployment
kubectl get po.rs,deploy
复制代码
使用下面的命令和yaml文件从新建立相应资源:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hostnetwork-deployment
namespace: kube-system
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.4
hostNetwork: true
复制代码
kubectl apply -f nginx-host-network-deployment.yaml
kubectl get po,rs,deploy
复制代码
可见replica set controller并无建立相对应的pod,缘由以下:
Warning FailedCreate 2m38s (x17 over 8m5s) replicaset-controller Error creating: pods "nginx-hostnetwork-deployment-fd75d78b-" is forbidden: unable to validate against any pod security policy: [spec.securityContext.hostNetwork: Invalid value: true: Host network is not allowed to be used]
注意:
上面的错误显示在建立deployment时试图获取已经被限制的资源,k8s集群不容许这样的行为。
在这部分,我将经过对一些controllers(deamon-set-controller,replicaset-controller,job-controller)的调用user和service account授予一些特殊权限。
首先,我先建立role binding。
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: psp-permissive
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: psp-permissive
subjects:
- kind: ServiceAccount
name: daemon-set-controller
namespace: kube-system
- kind: ServiceAccount
name: replicaset-controller
namespace: kube-system
- kind: ServiceAccount
name: job-controller
namespace: kube-system
复制代码
使用如下命令建立role binding:
kubectl apply -f psp-permissive-cluster-role-binding.yaml
复制代码
接下来我将从新建立deployment并在pod中使用被restrictive policy限制使用的资源。当前deployment与前面deployment的区别在于如今在kube-system命名空间中建立deployment,之前则是在default命名空间中,这主要是因为刚刚对kube-system授予permissive policy权限。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-hostnetwork-deployment
namespace: kube-system
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.15.4
hostNetwork: true
复制代码
使用下面命令,从新建立deployment资源:
kubectl apply -f nginx-host-network-deployment-kube-system.yaml
复制代码
使用下面命令,验证pod是否正常运行:
kubectl get po,rs,deploy -n kube-system | grep hostnetwork
复制代码
注意:因为已经对kube-system命名空间的user和service account受权使用hostNetwork,可见nginx-hostnetwork-deployment pod已经部署在kube-system命名空间。
上面的内容演示了如何经过使用PSP受权使用特殊资源,在k8s集群中实现Pod Security Policy安全策略。
本文翻译自Kubernetes Pod Security Policy,行文时略有修改