pod安全策略PSP-3

runAsUser

刚刚创建了pod1,那么我们先进入到pod1里去之后执行whoami命令。

root@vms61:~/demo5# kubectl exec -it pod1 -- bash
root@vms63:/# whoami
root
root@vms63:/# exit
exit
root@vms61:~/demo5#

可以看到容器里的进程是以root身份运行的,然后删除pod1。

root@vms61:~/demo5# kuser delete pod pod1
pod "pod1" deleted
root@vms61:~/demo5#
root@vms61:~/demo5# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  securityContext:
    runAsUser: 1000
  hostNetwork: false
  ...输出...
root@vms61:~/demo5#
root@vms61:~/demo5# kubectl apply -f pod1.yaml 
pod/pod1 created
root@vms61:~/demo5# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          4s
root@vms61:~/demo5# kubectl exec -it pod1 -- bash
I have no name!@pod1:/$ whoami
whoami: cannot find name for user ID 1000
I have no name!@pod1:/$ exit
exit
command terminated with exit code 1
root@vms61:~/demo5# 
root@vms61:~/demo5# kubectl delete  pod pod1
pod "pod1" deleted
root@vms61:~/demo5#
root@vms61:~/demo5# cat mypsp1.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: mypsp1
spec:
  privileged: false  #不允许创建特权pod
  hostNetwork: true #允许pod使用hostNetwork
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  runAsUser:
    #rule: RunAsAny
    rule: 'MustRunAs'
    ranges:
      - min: 1500
        max: 2000
  ...输出...
root@vms61:~/demo5# 

再次创建pod1。

root@vms61:~/demo5# kubectl apply -f pod1.yaml
Error from server (Forbidden): error when creating "pod1.yaml": pods "pod1" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.containers[0].securityContext.runAsUser: Invalid value: 1000: must be in the ranges: [{1500 2000}]]
root@vms61:~/demo5#

这里创建失败了,因为在mypsp1里指定运行pod时,pod里进程必须是以1500~2000的UID来运行,但是pod1里的UID指定的是1000,所以运行失败。

修改pod1.yaml的内容,让容器里的进程以uid=1800来运行如下并创建pod1,查看pod1正常之后删除pod1。

root@vms61:~/demo5# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  securityContext:
    runAsUser: 1800
  hostNetwork: false
  ...输出...
root@vms61:~/demo5# 
root@vms61:~/demo5# kubectl apply -f pod1.yaml 
pod/pod1 created
root@vms61:~/demo5# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          2s
root@vms61:~/demo5# kubectl delete  pod pod1 
pod "pod1" deleted
root@vms61:~/demo5# 

可以看到pod1是可以正常运行的,然后把pod1删除。

修改mypsp1.yaml,仍然把 runAsUser:设置为rule: RunAsAny,并设置可以使用所有类型的卷并让其生效。

root@vms61:~/demo5# cat mypsp1.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: mypsp1
spec:
  privileged: false  #不允许创建特权pod
  hostNetwork: true #允许pod使用hostNetwork
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  runAsUser:
    rule: RunAsAny
  ...输出...
root@vms61:~/demo5#
root@vms61:~/demo5# kubectl apply -f mypsp1.yaml 
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/mypsp1 configured
root@vms61:~/demo5#

deployment

root@vms61:~/demo5# cat web1.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: web1
  name: web1
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web1
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: web1
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - image: nginx
        name: nginx
        imagePullPolicy: IfNotPresent
        resources: {}
status: {}
root@vms61:~/demo5# 
root@vms61:~/demo5# kubectl get deploy
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web1   0/2     0            0           12s
root@vms61:~/demo5# kubectl get pods
No resources found in default namespace.
root@vms61:~/demo5#
root@vms61:~/demo5# kubectl get ev
LAST SEEN   TYPE      REASON              OBJECT                       MESSAGE
2s          Warning   FailedCreate        replicaset/web1-665f6b46cb   Error creating: pods "web1-665f6b46cb-" is forbidden: PodSecurityPolicy: unable to admit pod: []
4s          Normal    ScalingReplicaSet   deployment/web1              Scaled up replica set web1-665f6b46cb to 2
root@vms61:~/demo5#
root@vms61:~/demo5# kubectl delete -f web1.yaml 
deployment.apps "web1" deleted
root@vms61:~/demo5#
root@vms61:~/demo5# kubectl get sa -n kube-system | grep replicaset
replicaset-controller                1         58d
root@vms61:~/demo5#

file

root@vms61:~/demo5# kubectl create clusterrolebinding cbind3 --clusterrole=crole2 --serviceaccount=kube-system:replicaset-controller
clusterrolebinding.rbac.authorization.k8s.io/cbind3 created
root@vms61:~/demo5#

file

再次创建deploy。

root@vms61:~/demo5# kubectl apply -f web1.yaml 
deployment.apps/web1 created
root@vms61:~/demo5# kubectl get deploy
NAME   READY   UP-TO-DATE   AVAILABLE   AGE
web1   2/2     2            2           3s
root@vms61:~/demo5# kubectl get pods
NAME                    READY   STATUS    RESTARTS   AGE
web1-665f6b46cb-792c2   1/1     Running   0          5s
web1-665f6b46cb-wppv5   1/1     Running   0          5s
root@vms61:~/demo5# 
root@vms61:~/demo5# kubectl delete -f web1.yaml 
deployment.apps "web1" deleted
root@vms61:~/demo5# 

两个PSP规则冲突谁生效

如果两个PSP规则且配置冲突的话,那么允许的优先级要高于拒绝的优先级。比如再创建一个PSP规则mypsp2允许创建特权pod,对应的yaml文件如下。

root@vms61:~/demo5# cat mypsp2.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: mypsp2
spec:
  privileged: true
  ...输出...
root@vms61:~/demo5#

然后创建此PSP规则。

root@vms61:~/demo5# kubectl apply -f mypsp2.yaml 
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/mypsp2 created
root@vms61:~/demo5# kubectl get psp
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
NAME     PRIV           CAPS   SELINUX    RUNASUSER   FSGROUP    SUPGROUP
mypsp1   false                        RunAsAny   RunAsAny        RunAsAny      RunAsAny       ...
mypsp2   true                         RunAsAny   RunAsAny        RunAsAny       RunAsAny       ...
root@vms61:~/demo5# 

凡是能访问到mypsp1和mypsp2的用户是都能创建出来特权pod的,比如管理员可以访问到所有的psp规则,所以管理员能够创建出来特权pod。修改pod1.yaml内容如下。

root@vms61:~/demo5# cat pod1.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    run: pod1
  name: pod1
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    command: ["sh","-c","sleep 1000000"]
    name: pod1
    resources: {}
    securityContext:
      privileged: true
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
root@vms61:~/demo5#
root@vms61:~/demo5# kubectl apply -f pod1.yaml 
pod/pod1 created
root@vms61:~/demo5# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          3s
root@vms61:~/demo5# 

删除pod1。

root@vms61:~/demo5# kubectl delete  pod pod1 
pod "pod1" deleted
root@vms61:~/demo5#

下面使用lduan用户创建pod1。

root@vms61:~/demo5# kuser apply -f pod1.yaml 
Error from server (Forbidden): error when creating "pod1.yaml": pods "pod1" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
root@vms61:~/demo5#

发现是创建不了特权pod的,因为lduan用户只能访问mypsp1而访问不了mypsp2。
如果打算让lduan用户只能在命名空间ns1里创建特权pod,在其他命名空间里不能创建特权pod的话,那么我们可以通过在ns1命名空间里创建一个集群角色crole3可以使用mypsp2的权限,然后在ns1里创建一个rolebinding(不是clusterrolebinding)把crole3授权给lduan,用户如下图。
file

crole2是通过clusterrolebinding授权给lduan用户的,那么lduan用户在任何命名空间都能访问到mypsp1,所以不能创建特权pod。crole3通过在ns1命名空间里通过rolebinding授权lduan用户,所以lduan用户只在ns1命名空间能访问mypsp2,在ns1里lduan既能访问mypsp1又能访问mypsp2,允许优先级高于拒绝优先级,所以lduan用户在ns1命名空间里能创建特权pod。

创建crole3让其具备使用mypsp2的权限。

root@vms61:~/demo5# kubectl create clusterrole crole3 --verb=use --resource=psp --resource-name=mypsp2
clusterrole.rbac.authorization.k8s.io/crole3 created
root@vms61:~/demo5#

在ns1命名空间里创建名字为rbind1的rolebinding,让lduan用户可以使用crole3的权限。

root@vms61:~/demo5# kubectl create rolebinding rbind1 --clusterrole=crole3 --user=lduan -n ns1
rolebinding.rbac.authorization.k8s.io/rbind1 created
root@vms61:~/demo5#

然后测试

root@vms61:~/demo5# kuser apply -f pod1.yaml 
Error from server (Forbidden): error when creating "pod1.yaml": pods "pod1" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
root@vms61:~/demo5# 

发现在当前命名空间(default)空间里创建不出来特权pod,然后在ns1里创建pod1。

root@vms61:~/demo5# kuser apply -f pod1.yaml -n ns1
pod/pod1 created
root@vms61:~/demo5# kuser get pods -n ns1
NAME   READY   STATUS    RESTARTS   AGE
pod1   1/1     Running   0          4s
root@vms61:~/demo5# 

这里是可以正常创建出来的,然后删除pod1。

root@vms61:~/demo5# kuser delete pod pod1 -n ns1
pod "pod1" deleted
root@vms61:~/demo5#

还原环境

现在一共用到的角色如下。
file
删除cbind2,cbind3,rbind1 和crole2,crole3

root@vms61:~/demo5# kubectl delete clusterrolebinding cbind{2,3}
clusterrolebinding.rbac.authorization.k8s.io "cbind2" deleted
clusterrolebinding.rbac.authorization.k8s.io "cbind3" deleted
root@vms61:~/demo5# 
root@vms61:~/demo5# kubectl delete clusterrole crole{2,3}
clusterrole.rbac.authorization.k8s.io "crole2" deleted
clusterrole.rbac.authorization.k8s.io "crole3" deleted
root@vms61:~/demo5# 
root@vms61:~/demo5# kubectl delete rolebinding rbind1 -n ns1

rolebinding.rbac.authorization.k8s.io "rbind1" deleted
root@vms61:~/demo5#

删除mypsp1和mypsp2

root@vms61:~/demo5# kubectl delete  psp mypsp{1,2}
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy "mypsp1" deleted
podsecuritypolicy.policy "mypsp2" deleted
root@vms61:~/demo5# 

关闭PSP

编辑/etc/kubernetes/manifests/kube-apiserver.yaml,把

  • --enable-admission-plugins=NodeRestriction,PodSecurityPolicy修改为
  • --enable-admission-plugins=NodeRestriction
    保存退出之后,重启kubelet。

相关新闻

                                                                                                                                    RHCE9学习指南连载,点击阅读