# 官方提供@yunTaoScripts PSP 🔥🔥
利用k8s集群自带的功能来提升集群安全性。基于准入控制器实现。pod security policy -> pod安全策略,用于限定我们创建特定类型的pod。
- 启用特权pod
root@vms33:~# cat pod1-privilege.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod1-privi
name: pod1-privi
spec:
nodeName: vms34.rhce.cc
terminationGracePeriodSeconds: 0
imagePullSecrets:
- name: my-secret
containers:
- image: 192.168.26.150/baseos/nginx:v1
imagePullPolicy: IfNotPresent
name: pod1-privi
securityContext:
privileged: true
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
root@pod1-privi:/# cat /proc/sys/vm/swappiness
60
root@pod1-privi:/# echo 1 > /proc/sys/vm/swappiness
如果没有特权模式,这一步执行失败
root@pod1-noprivi:/# echo 1 > /proc/sys/vm/swappiness
bash: /proc/sys/vm/swappiness: Read-only file system
1.25 后将无法使用psp
root@vms33:~# kubectl get psp
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES
controller false RunAsAny MustRunAs MustRunAs MustRunAs true configMap,secret,emptyDir
speaker true NET_RAW RunAsAny RunAsAny RunAsAny RunAsAny true configMap,secret,emptyDir
- 删除自带psp 规则
root@vms33:~# kubectl get psp -oyaml > psp.bak.yaml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
root@vms33:~# kubectl delete -f psp.bak.yaml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy "controller" deleted
podsecuritypolicy.policy "speaker" deleted
root@vms33:~# kubectl get psp
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
No resources found
# 启用PSP准入控制器
root@vms33:~# grep enable-admission /etc/kubernetes/manifests/kube-apiserver.yaml
- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy
root@vms33:~# kubectl apply -f pod1.yaml
Error from server (Forbidden): error when creating "pod1.yaml": pods "pod1" is forbidden: PodSecurityPolicy: no providers available to validate pod request
一定要创建psp 规则
- 启用PSP 功能后,如果没有创建psp规则,任何用户不可以创建pod。
# 创建 psp 规则
# 不允许提权pod 创建
root@vms33:~# cat psp1.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: example
spec:
privileged: false # 不允许提权的 Pod!
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
- 创建pod
root@vms33:~# kubectl apply -f pod1-privilege.yaml
Error from server (Forbidden): error when creating "pod1-privilege.yaml": pods "pod1-privi" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
root@vms33:~# kubectl apply -f pod1-noprivilege.yaml
pod/pod1-noprivi created
root@vms33:~# kubectl get pod
NAME READY STATUS RESTARTS AGE
pod1-noprivi 1/1 Running 0 7s
非root 用户 可能没有权限访问psp,因此无法创建pod
- 给 john 授权使用psp
root@vms33:~# kubectl create clusterrole use-psp --verb use --resource psp --resource-name example
root@vms33:~# kubectl create clusterrolebinding cbind-use-psp --clusterrole use-psp --user john
clusterrolebinding.rbac.authorization.k8s.io/cbind-use-psp created
# 允许使用宿主机网络空间(默认禁止)
root@vms33:~# kubectl apply -f pod1-noprivilege-hostnetwok.yaml
Error from server (Forbidden): error when creating "pod1-noprivilege-hostnetwok.yaml": pods "pod1-noprivi-host" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.securityContext.hostNetwork: Invalid value: true: Host network is not allowed to be used]
- 允许hostNetwok PSP
root@vms33:~# grep host psp2.yaml
hostNetwork: true
root@vms33:~# cat psp2.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp2
spec:
hostNetwork: true # 允许使用主机网络
privileged: false # 不允许提权的 Pod!
# 以下内容负责填充一些必需字段。
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
root@vms33:~# cat pod1-noprivilege-hostnetwok.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: pod1-noprivi-host
name: pod1-noprivi-host
spec:
hostNetwork: true
nodeName: vms34.rhce.cc
terminationGracePeriodSeconds: 0
imagePullSecrets:
- name: my-secret
containers:
- image: 192.168.26.150/baseos/nginx:v1
imagePullPolicy: IfNotPresent
name: pod1-noprivi-host
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
# 限制只能挂载特定类型的卷。
spec:
privileged: false
# 防止权限升级到 root
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
# 允许的核心卷类型.
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
# 限制只能挂载特定目录。
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
allowedHostPaths:
# 下面的设置允许 "/foo"、"/foo/"、"/foo/bar" 等路径,但禁止
# "/fool"、"/etc/foo" 这些路径。
# "/foo/../" 总会被当作非法路径。
- pathPrefix: "/foo"
readOnly: true # 仅允许只读模式挂载
# 限制只能某个用户启动
runAsUser:
# 要求容器在没有 root 权限的情况下运行
rule: 'MustRunAsNonRoot'
supplementalGroups:
rule: 'MustRunAs'
ranges:
# 禁止添加 root 组
- min: 1
max: 65535
# 限制hostPort 端口范围
- pod 使用hostPort 时的 范围限制
spec:
privileged: true
allowPrivilegeEscalation: true
allowedCapabilities:
- '*'
volumes:
- '*'
hostNetwork: true
hostPorts: ###端口映射范围
- min: 0
max: 65535
# 允许rs 控制器 访问psp
root@vms33:~# kubectl create deployment dp1 --image nginx
deployment.apps/dp1 created
root@vms33:~# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
dp1 0/1 0 0 14s
root@vms33:~# kubectl get event
LAST SEEN TYPE REASON OBJECT MESSAGE
2s Warning FailedCreate replicaset/dp1-5fb8655b4f Error creating: pods "dp1-5fb8655b4f-" is forbidden: PodSecurityPolicy: unable to admit pod: []
23s Normal ScalingReplicaSet deployment/dp1 Scaled up replica set dp1-5fb8655b4f to 1
无法创建deployment 原因
deployment 首先会创建rs 控制器。每个控制器都有一个sa,用于各种操作。但是启用psp后,rs控制器的 sa 不具备访问psp 规则的权限,因此无法创建pod。
root@vms33:~# kubectl get psp psp2 -oyaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp2
resourceVersion: "698032"
uid: a3ce138f-0e88-4888-bdac-1cce1512d0e9
spec:
allowPrivilegeEscalation: true
fsGroup:
rule: RunAsAny
hostNetwork: true
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- '*'
root@vms33:~# kubectl get clusterrole use-psp -oyaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: "2022-09-17T12:33:44Z"
name: use-psp
resourceVersion: "696044"
uid: 0ca44b28-3c33-422e-8fcd-ddc0ae013f0c
rules:
- apiGroups:
- policy
resourceNames:
- example
resources:
- podsecuritypolicies
verbs:
- use
root@vms33:~# kubectl get sa -n kube-system | grep replicaset
replicaset-controller 0 23d
- 给命名空间单个sa 授权
root@vms33:~# kubectl create clusterrolebinding cbind-rs-usepsp --clusterrole use-psp --serviceaccount kube-system:replicaset-controller
- 给kube-system命名空间所有sa授权
root@vms33:~# kubectl create clusterrolebinding cbind-rs-usep-all-sa --clusterrole use-psp --group system:serviceaccounts
- 此时 rs 可以访问到psp,所以可以创建pod
root@vms33:~# kubectl get deployments.apps dp1
NAME READY UP-TO-DATE AVAILABLE AGE
dp1 3/3 3 3 12m
psp生效范围
PSP 全局生效,没有命名空间限制
# 限制用户在特定ns满足psp规则
思路:
- 首先创建psp1 ,拒绝特权pod。
- 创建psp2,允许特权pod。
- 给john 授权rolebinding访问psp2。
找出所有授权给john 的 clusterrolebinding,并删除。
root@vms33:~# kubectl get clusterrolebindings.rbac.authorization.k8s.io -owide| grep john
← 快速链接