k8s安全机制:Pod Security Policy与Security Context
自从首次引入 PodSecurityPolicy 以来, PSP 存在一些严重的可用性问题, 只有做出断裂式的改变才能解决。PodSecurityPolicy (PSP) 在 Kubernetes 1.21 中被弃用, 在Kubernetes v1.25会被移除。替代方案Pod Security Standard(Pod安全标准)。使用 Pod 安全标准的 PSP 来获得和目前 PSP 替代策略相
一、介绍
1.PSP
Pod Security Policy是一个准入控制器。通过RBAC授予users和service accounts启动或更新pods时使用服务器资源的权限。是集群范围内的资源对象,不属于命名空间范围。
2.Security Context
kubernetes可以为pod设置应用程序运行所需的权限或者访问控制等安全设置,涉及多种Linux Kernel安全相关的系统参数,这些安全设置被称为Security Context,在Pod或Container级别通过securityContext字段进行设置(如果在Pod和Container级别都设置了相同的安全字段,则同期将使用Container级别的设置)。摘自《kubernetes权威指南第五版》
3.二者的关联
管理员设置集群范围的PodSecurityPolicy策略会对Pod的SecurityContext安全设置进行校验,对于不满足PodSecurityPolicy策略的Pod,系统将禁止创建。
简单来说,SecurityContext是pod中一段具体的配置,PodSecurityPolicy是用来校验SecurityContext符不符合要求
Note: PodSecurityPolicy 在 Kubernetes v1.21 中被弃用,在 Kubernetes v1.25 中被移除。代替方案是PodSecurityStandard,下面会介绍
4.psp控制项说明
4.1特权模式
privilege:是否允许容器以特权模式运行
4.2宿主机命名空间(namespace)相关
- hostPID:是否允许容器共享宿主机的进程ID命名空间
- hostIPC:是否允许容器共享宿主机的IPC命名空间
- hostNetwork:否允许Pod使用宿主机的网络命名空间,使用hostNetwork的pod将可以访问宿主机的各个网卡
- hostPorts:是否允许Pod使用宿主机的端口号,可以通过hostPortRange字段设置允许使用的端口号范围,以[min,max]设置最小端口号和最大端口号
4.3存储卷和文件系统相关
- Volumes:允许pod使用的存储卷类型,设置为“*”表示不受限制
- FSGroup:
- AllowedHostPaths:允许pod使用宿主机的hostPath路径名称,可以通过pathPrefix字段设置路径的前缀,并设置是否仅允许以只读模式挂载,举个栗子:
apiVersion:policy/v1beta1
kind:PodSecurityPolicy
metadata:
name: allow-hostpath-volumes
spec:
。。。。
volumes:
- flexVolume
allowedFlexVolumes:
- driver: example/lvm
- driver: example/cifs
- ReadOnlyRootFilesystem:根目录只读权限
4.4FlexVolume驱动相关
allowedFlexVolumes用于对类型为flexVolume的存储卷设置允许使用的驱动类型,控制表示没有限制。
4.5用户和组的相关配置
- RunAsUser:设置运行容器的UID,rule可被设置为MustRunAs、MustRunAsNonRoot、RunAsAny
MustRunAs:需要设置UID的范围,要求Pod或Container的securityContext.runAsUser设置的值必须属于该UID范围,如未设置,则系统将自动设置securityContext.runAsUse的值为UID的最小值。
MustRunAsNonRoot:必须以非root用户运行容器
RunAsAny:不限制UserID的范围,Pod或Container的securityContext.runAsUser可被设置为任意UID
- RunAsGroup:设置运行容器的GID,rule可被设置为MustRunAs、MustRunAsNonRoot、RunAsAny
- SupplementalGroups:设置运行容器的用户允许属于的额外GIDrule可被设置为MustRunAs、MustRunAsNonRoot、RunAsAny
4.6提升权限的相关配置
- AllowPrivilegeEscalation:默认值为true,允许容器提权
- DefaultAllowPrivilegeEscalation:设置AllowPrivilegeEscalation的默认值
4.7linux能力相关配置
这块比较难,需要了解Linux Capabilities
- AllowedCapabilities:设置容器可以使用的linux能力列表,设置为“*”表示允许使用linux的所有能力
- RequiredDropCapabilities:设置必须从容器中删除的linux能力列表
- DefaultAddCapabilities:设置默认为容器添加的linux能力列表
4.8SELinux相关配置
通过seLinux字段设置SELinux参数rule可被设置为MustRunAs、RunAsAny
4.9其他Linux相关配置
- AllowedProcMountTypes
- AppArmor
- Seccomp
- Sysctl
二、PSP的工作机制
1.开启psp准入控制
[root@k8s-master ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
......
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.0.37
- --allow-privileged=true
- --authorization-mode=Node,RBAC
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-admission-plugins=NodeRestriction,PodNodeSelector,PodSecurityPolicy
......
修改之后保存退出,kube-apiserver会自动重启。
2.创建Pod
[root@k8s-master test]# vim test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
[root@k8s-master test]# kubectl create -f test-pod.yaml
Error from server (Forbidden): error when creating "test-pod.yaml": pods "nginx" is forbidden: PodSecurityPolicy: no providers available to validate pod request
此时创建pod会失败
[root@k8s-master test]# journalctl -f -u kubelet
-- Logs begin at Wed 2023-02-08 10:40:25 CST. --
Apr 27 17:01:31 k8s-master kubelet[3621]: E0427 17:01:31.752259 3621 kubelet.go:1661] Failed creating a mirror pod for "kube-apiserver-k8s-master_kube-system(b53d99a0c0acc014c351c2a89eef045d)": pods "kube-apiserver-k8s-master" is forbidden: PodSecurityPolicy: no providers available to validate pod request
Apr 27 17:03:00 k8s-master kubelet[3621]: E0427 17:03:00.752741 3621 kubelet.go:1661] Failed creating a mirror pod for "kube-apiserver-k8s-master_kube-system(b53d99a0c0acc014c351c2a89eef045d)": pods "kube-apiserver-k8s-master" is forbidden: PodSecurityPolicy: no providers available to validate pod reques
[root@k8s-master test]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
calico-kube-controllers-577f77cb5c-9b84g 1/1 Running 0 35d
calico-node-6p7b4 1/1 Running 1 35d
calico-node-fpp6m 1/1 Running 0 35d
calico-node-lkcft 1/1 Running 0 35d
calico-node-qtcn6 1/1 Running 1 35d
calicoctl 1/1 Running 0 35d
coredns-7f89b7bc75-n5255 1/1 Running 0 35d
coredns-7f89b7bc75-s5xh7 1/1 Running 0 35d
eip-nfs-nfs-7cd8fcb6f9-2xzfc 1/1 Running 14 35d
etcd-k8s-master 1/1 Running 0 35d
kube-controller-manager-k8s-master 1/1 Running 9 35d
kube-proxy-26vvr 1/1 Running 0 16d
kube-proxy-4vhwc 1/1 Running 0 16d
kube-proxy-mjdgf 1/1 Running 0 16d
kube-proxy-txpk4 1/1 Running 0 16d
kube-scheduler-k8s-master 1/1 Running 8 35d
metrics-server-c7d74c45-gl4lg 1/1 Running 0 31d
Note:开启PodSecurityPolicy准入控制器后,系统中还没有任何PodSecurityPolicy策略时,k8s默认不允许创建任何Pod,需要创建适合的PSP策略和相应的RBAC赋权策略,Pod才能创建成功
3.创建PSP
[root@k8s-master test]# vim psp.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp
spec:
privileged: false ## 禁止特权模式启动
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
[root@k8s-master test]# kubectl apply -f psp.yaml
podsecuritypolicy.policy/psp created
[root@k8s-master test]# kubectl get psp
NAME PRIV CAPS SELINUX RUNASUSER FSGROUP SUPGROUP READONLYROOTFS VOLUMES
psp false RunAsAny RunAsAny RunAsAny RunAsAny false *
再次创建Pod就能成功
[root@k8s-master test]# kubectl apply -f test-pod.yaml
pod/nginx created
[root@k8s-master test]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 12s
修改pod为特权模式就会失败
[root@k8s-master test]# vim test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true
[root@k8s-master test]# kubectl apply -f test-pod.yaml
Error from server (Forbidden): error when creating "test-pod.yaml": pods "nginx" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
Note:这个示例用的sa是default sa,整个示例没有RBAC授权过程,但是自建的sa必须要授权,关于这一点我查了很久没有结果,那就当default sa有特殊权限吧,这个问题不用再纠结,下面会演示自建sa然后RBAC授权的过程
4.创建命名空间和SA
[root@k8s-master test]# kubectl create namespace test
namespace/test created
[root@k8s-master test]# kubectl create sa -n test test-user
serviceaccount/test-user created
授权clusterrole‘edit’权限,使sa test-user有权限创建pod
[root@k8s-master test]# kubectl get clusterrole | grep edit
edit 2023-10-09T03:14:14Z
system:aggregate-to-edit 2023-10-09T03:14:14Z
[root@k8s-master test]# kubectl create rolebinding -n test test-user --clusterrole=edit --serviceaccount=test:test-user
rolebinding.rbac.authorization.k8s.io/test-user created
用新建的sa发布测试
[root@k8s-master test]# kubectl --as=system:serviceaccount:test:test-user -n test apply -f app-nginx.yaml
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "apps/v1, Resource=deployments", GroupVersionKind: "apps/v1, Kind=Deployment"
Name: "nginx-app", Namespace: "test"
from server for: "app-nginx.yaml": deployments.apps "nginx-app" is forbidden: User "system:serviceaccount:test:test-user" cannot get resource "deployments" in API group "apps" in the namespace "test"
[root@k8s-master test]# kubectl auth can-i use psp/psp --as=system:serviceaccount:test:test-user -n test
Warning: resource 'podsecuritypolicies' is not namespace scoped in group 'policy'
no ## 授权验证,目前无权限
上面的报错可以看出,目前test-user这个sa不能使用psp这个Pod Security Policy,需要做role和rolebinding授权
5.创建role和rolebinding授权
[root@k8s-master test]# cat psp-rbac.yaml
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: test
name: psp-role
rules:
- apiGroups: ["policy"]
resources: ["podsecuritypolicies"]
resourceNames: ["psp"]
verbs: ["use"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: psp-rolebinding
namespace: test
subjects:
- kind: ServiceAccount
name: test-user
namespace: test
roleRef:
kind: Role
name: psp-role
apiGroup: rbac.authorization.k8s.io
[root@k8s-master test]# kubectl apply -f psp-rbac.yaml
role.rbac.authorization.k8s.io/psp-role created
rolebinding.rbac.authorization.k8s.io/psp-rolebinding created
[root@k8s-master test]# kubectl auth can-i use psp/psp --as=system:serviceaccount:test:test-user -n test
Warning: resource 'podsecuritypolicies' is not namespace scoped in group 'policy'
yes ## 授权验证成功
[root@k8s-master test]# kubectl get rolebinding -n test
NAME ROLE AGE
psp-rolebinding Role/psp-role 20m
test-user ClusterRole/edit 2m51s
6.创建pod测试
[root@k8s-master test]# kubectl --as=system:serviceaccount:test:test-user -n test apply -f app-nginx.yaml
pod/nginx-app created
[root@k8s-master test]# kubectl get pod -n test -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-app 1/1 Running 0 116s 100.64.168.169 izbp1a1yp5oxc1e2haou4wz <none> <none>
查看pod 注解,发现自动注入一条psp信息
[root@k8s-master test]# kubectl get pod nginx-app -n test -o custom-columns=ANNOTATIONS:.metadata.annotations
ANNOTATIONS
map[cni.projectcalico.org/podIP:100.64.168.169/32 kubectl.kubernetes.io/last-applied-configuration:{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"nginx-app","namespace":"test"},"spec":{"containers":[{"image":"nginx","name":"nginx"}]}}
kubernetes.io/psp:psp]
7.测试特权模式
[root@k8s-master test]# kubectl delete -f app-nginx.yaml
pod "nginx-app" deleted
添加特权配置
[root@k8s-master test]# cat app-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-app
namespace: test
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true
[root@k8s-master test]# kubectl --as=system:serviceaccount:test:test-user -n test apply -f app-nginx.yaml
pod/nginx-app created
Error from server(Forbidden): error when creating "app-nginx.yaml": pods "nginx-app" is forbidden: unable to validate against any pod security polic: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
三、Pod Security Standard介绍
1.为什么要用Pod Security Standard
自从首次引入 PodSecurityPolicy 以来, PSP 存在一些严重的可用性问题, 只有做出断裂式的改变才能解决。PodSecurityPolicy (PSP) 在 Kubernetes 1.21 中被弃用, 在Kubernetes v1.25会被移除。替代方案Pod Security Standard(Pod安全标准)。
使用 Pod 安全标准的 PSP 来获得和目前 PSP 替代策略相似的功能。 如果你将基线策略或限制策略绑定到 system:serviceaccounts 组来设置集群默认值, 然后使用 ServiceAccount 绑定 在某些命名空间下根据需要制定更宽松的策略,就可以避免许多 PSP 陷阱并轻松迁移到 PSP 替代策略。 如果你的需求比这复杂得多,那么建议将精力花在采用比上面提到的功能更全的某个外部准入控制器。
Pod 安全性准入(Pod Security Admission)在 Kubernetes v1.22 作为 Alpha 特性发布, 在 Kubernetes v1.23 中作为 Beta 特性默认可用。从 1.25 版本起, 此特性进阶至正式发布(Generally Available)。
2.Pod Security Standard的策略
Pod 安全性标准定义了三种不同的策略(Policy),以广泛覆盖安全应用场景。 这些策略是叠加式的(Cumulative),安全级别从高度宽松至高度受限。 本指南概述了每个策略的要求
Profile | 描述 |
---|---|
Privileged | 不受限制的策略,提供最大可能范围的权限许可。此策略允许已知的特权提升。 |
Baseline | 限制性最弱的策略,禁止已知的策略提升。允许使用默认的(规定最少)Pod 配置。 |
Restricted | 限制性非常强的策略,遵循当前的保护 Pod 的最佳实践。 |
3.Profile 细节
3.1Privileged
Privileged 策略是有目的地开放且完全无限制的策略。 此类策略通常针对由特权较高、受信任的用户所管理的系统级或基础设施级负载。
Privileged 策略定义中限制较少。默认允许的(Allow-by-default)实施机制(例如 gatekeeper) 可以缺省设置为 Privileged。 与此不同,对于默认拒绝(Deny-by-default)的实施机制(如 Pod 安全策略)而言, Privileged 策略应该禁止所有限制.
3.2Baseline
Baseline 策略的目标是便于常见的容器化应用采用,同时禁止已知的特权提升。 此策略针对的是应用运维人员和非关键性应用的开发人员。
3.3Restricted
Restricted 策略旨在实施当前保护 Pod 的最佳实践,尽管这样作可能会牺牲一些兼容性。 该类策略主要针对运维人员和安全性很重要的应用的开发人员,以及不太被信任的用户。
pod安全标准就大概介绍这么多,更多信息参考k8s官网,这里就不当文档搬运工了~~~
https://kubernetes.io/docs/concepts/security/pod-security-admission/
更多推荐
所有评论(0)