一、概述
Pod Security Policies(Adminssion Controller)授予users和service accounts创建或更新pods使用资源的权限。这是一种集群级别的资源类型,用来限制pod对敏感资源的使用。它还能控制Pod的各个安全方面。
举例来说PSP可以做的事情:
【温馨提示】PodSecurityPolicy 在 Kubernetes v1.21 中被弃用, 在 Kubernetes v1.25 中被移除。
作为代替,你可以使用下边任一方法执行类似的限制,或者同时使用下边这两种方法。
官方文档:
关于 k8s RBAC的介绍,可以参考我这篇文章:Kubernetes(k8s)权限管理RBAC解读
二、PodSecurityPolicy 的发展1)以前为何须要 PodSecurityPolicy?2)现在为何 PodSecurityPolicy 要消失?三、PSP 简单使用
因为PSP在高版本中早已不再使用了,所以这儿稍为了解即可。目前,如果我们想要使用PSP,需要自动配置启动。PSP控制pod的方面宽容如下:
1)开启PSP
在Master上编辑/etc/kubernetes/manifests/kube-apiserver.yaml文件,然后我们须要在command下的enable-admission-plugins下添加PodSecurityPolicy
command:
- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy
重启kubelet
systemctl restart kubelet.service
【注意】开启PodSecurityPolicy功能后,即使没有使用任何安全策略,都会促使创建pods(包括调度任务重新创建pods)失败
2)示例演示1、没有PSP场景测试
通过下边的deployment yaml文件测试在没有PSP策略的情况下是否可以创建pod:
cat >nginx-deployment.yaml<
使用下边的命令创建deployment资源:
kubectl apply -f nginx-deployment.yaml
使用下边的命令检测pod是否创建:
kubectl get pods,replicasets,deployments
通过上图可见deployments和relicaset正在运行,由于缺乏PSP policy,集群并没有创建相应的pods。
2、定义PSP
这里定义两个不同权限的PSP策略:
【1】资源限制策略
下面是典型的限制资源使用的restrictive policy:
cat >default-restrict-psp.yaml<
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- 'configMap'
- 'downwardAPI'
- 'emptyDir'
- 'persistentVolumeClaim'
- 'secret'
- 'projected'
allowedCapabilities:
- '*'
EOF
【2】资源容许策略
下面是容许使用资源的permissive policy,多条permissive policy规则被拿来设置相应user或则sevice account使用相关类型的资源。
cat >permissive-psp.yaml<
上面两种poicies可以使用下边的命令创建对应的PSP资源:
kubectl apply -f default-restrict-psp.yaml
kubectl apply -f permissive-psp.yaml
核对psp是否创建成功与否:
kubectl get psp
下面将通过cluster role和cluster role binding在集群中使用刚刚定义的安全策略(Pod Security Policy)。
3、角色定义(Cluster Role)
关于restrictive policy的restrictive cluster role
cat >psp-restrictive-cluster-roleyaml<
关于permissive policy的permissive cluster role
cat >psp-permissive-cluster-roleyaml
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: psp-permissive
rules:
- apiGroups:
- extensions
resources:
- podsecuritypolicies
resourceNames:
- permissive
verbs:
- use
EOF
通过下边命令创建相应的cluster role资源:
kubectl apply -f psp-restrictive-cluster-roleyaml
kubectl apply -f psp-permissive-cluster-roleyaml
4、角色绑定(Cluster Role Bindings)
cat >psp-restrictive-cluster-role-binding.yaml<
上面的role binding会将restrictive cluster role绑定到所有的system service account。
使用下边的命令生成role binding资源:
kubectl apply -f psp-restrictive-cluster-role-binding.yaml
5、再测试验证
kubectl delete deploy nginx-deployment
kubectl get po,rs,deploy
通过上图可知,可以正常调度pod,启动pod了。
四、PodSecurity admission
Pod security admission 是 Kubernetes 内置的一种准入控制器,在 Kubernetes V1.23版本中这一特点门是默认开启的,在V1.22中须要通过 Kube-apiserver 参数--feature-gates="...,PodSecurity=true"开启。在高于V1.22的 Kuberntes 版本中也可以自行安装 Pod Security Admission Webhook。
1)podSecurity Standards
官方文档:
为了广泛的覆盖安全应用场景, Pod Security Standards 渐进式的定义了三种不同的 Pod 安全标准策略:
策略
描述
Privileged
不受限制的策略,提供最大可能范围的权限许可。此策略容许已知的特权提高。
Baseline
限制性最弱的策略,禁止已知的策略提高。允许使用默认的(规定最少)Pod 配置。
Restricted
限制性特别强的策略,遵循当前的保护 Pod 的最佳实践。
2)podSecurity admission
官方文档:
在 Kubernetes 集群中开启了 podSecurity admission 后,就可以通过给 namespace 设置 label 的方法来施行 Pod Security Standards。其中有三种设定模式可选用:
模式
描述
enforce
违反安全标准策略的 Pod 将被拒绝。
audit
违反安全标准策略触发向审计日志中记录的风波添加审计注释,但其他行为被准许。
warn
违反安全标准策略将触发面向用户的警告,但其他行为被准许。
label 设置模板解释:
# 设定模式及安全标准策略等级
# MODE必须是 `enforce`, `audit`或`warn`其中之一。
# LEVEL必须是`privileged`, `baseline`或 `restricted`其中之一
pod-security.kubernetes.io/:
# 此选项是非必填的,用来锁定使用哪个版本的的安全标准
# MODE必须是 `enforce`, `audit`或`warn`其中之一。
# VERSION必须是一个有效的kubernetes minor version(例如v1.23),或者 `latest`
pod-security.kubernetes.io/-version:
通过准入控制器配置文件,可以为 Pod security admission 设置默认配置:
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1beta1
kind: PodSecurityConfiguration
# Defaults applied when a mode label is not set.
#
# Level label values must be one of:
# - "privileged" (default)
# - "baseline"
# - "restricted"
#
# Version label values must be one of:
# - "latest" (default)
# - specific version like "v1.23"
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "privileged"
audit-version: "latest"
warn: "privileged"
warn-version: "latest"
exemptions:
# Array of authenticated usernames to exempt.
usernames: []
# Array of runtime class names to exempt.
runtimeClassNames: []
# Array of namespaces to exempt.
namespaces: []
podSecurity admission 可以从 username,runtimeClassName,namespace三个维度对 Pod 进行安全标准检测的豁免。
3)podSecurity standards 示例演示1、Baseline 策略
Baseline 策略目标是应用于常见的容器化应用,禁止已知的特权提高,在官方的介绍中此策略针对的是应用运维人员和非关键性应用开发人员,在该策略中包括:
必须严禁共享寄主命名空间、禁止容器特权、 限制 Linux 能力、禁止 hostPath 卷、限制宿主机端口、设定 AppArmor、SElinux、Seccomp、Sysctls 等。
违反 Baseline 策略存在的风险:
【1】创建名为 my-baseline-namespace 的 namespace,并设定 enforce 和 warn 两种模式都对应 Baseline 等级的 Pod 安全标准策略:
apiVersion: v1
kind: Namespace
metadata:
name: my-baseline-namespace
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: v1.23
pod-security.kubernetes.io/warn: baseline
pod-security.kubernetes.io/warn-version: v1.23
【2】创建一个违背 baseline 策略的 pod
apiVersion: v1
kind: Pod
metadata:
name: hostnamespaces2
namespace: my-baseline-namespace
spec:
containers:
- image: bitnami/prometheus:2.33.5
name: prometheus
securityContext:
allowPrivilegeEscalation: true
privileged: true
capabilities:
drop:
- ALL
hostPID: true
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
执行 apply 命令,显示不能设置 hostPID=true,securityContext.privileged=true,Pod 创建被拒绝,特权容器的运行,并且开启 hostPID,容器进程没有与宿主机进程隔离,容易导致 Pod 容器逃逸:
【3】创建不违背 baseline 策略的 pod,设定 Pod 的 hostPID=false,securityContext.privileged=false
apiVersion: v1
kind: Pod
metadata:
name: hostnamespaces2
namespace: my-baseline-namespace
spec:
containers:
- image: bitnami/prometheus:2.33.5
name: prometheus
securityContext:
allowPrivilegeEscalation: false
privileged: false
capabilities:
drop:
- ALL
hostPID: false
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
执行 apply 命令,pod 被准许创建。
2、Restricted 策略
Restricted 策略目标是施行当前保护 Pod 的最佳实践,在官方介绍中此策略主要针对运维人员和安全性很重要的应用开发人员,以及不太被信任的用户。该策略包含所有的 baseline 策略的内容,额外降低:限制可以通过 PersistentVolumes 定义的非核心卷类型、禁止(通过 SetUID 或 SetGID 文件模式)获得特权提高、必须要求容器以非 root 用户运行、Containers 不可以将 runAsUser 设置为 0、 容器组必须弃用 ALL capabilities 并且只容许添加 NET_BIND_SERVICE 能力。
Restricted 策略进一步的限制在容器内获取 root 权限,linux 内核功能。例如针对 kubernetes 网络的中间人攻击须要拥有 Linux 系统的 CAP_NET_RAW 权限来发送 ARP 包。
【1】创建名为 my-restricted-namespace的namespace,并设定 enforce 和 warn 两种模式都对应 Restricted 等级的 Pod 安全标准策略:
apiVersion: v1
kind: Namespace
metadata:
name: my-restricted-namespace
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: v1.23
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.23
【2】创建一个违背 Restricted 策略的 pod
apiVersion: v1
kind: Pod
metadata:
name: runasnonroot0
namespace: my-restricted-namespace
spec:
containers:
- image: bitnami/prometheus:2.33.5
name: prometheus
securityContext:
allowPrivilegeEscalation: false
securityContext:
seccompProfile:
type: RuntimeDefault
执行 apply 命令,显示必须设置 securityContext.runAsNonRoot=true,securityContext.capabilities.drop=["ALL"],Pod 创建被拒绝,容器以 root 用户运行时容器获取权限过大,结合没有 Drop linux 内核能力有 kubernetes 网络中间人攻击的风险。
【3】创建不违背 Restricted 策略的 pod,设定 Pod 的 securityContext.runAsNonRoot=true,Drop 所有 linux 能力。
apiVersion: v1
kind: Pod
metadata:
name: runasnonroot0
namespace: my-restricted-namespace
spec:
containers:
- image: bitnami/prometheus:2.33.5
name: prometheus
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
执行 apply 命令,pod 被准许创建。
4)Pod Security admission 当前局限性
如果你的集群中早已配置 PodSecurityPolicy,考虑把它们迁移到 podSecurity admission 是须要一定的工作量的。
首先须要考虑当前的 podSecurity admission 是否适宜你的集群,目前它借以满足开箱即用的最常见的安全需求,与 PSP 相比它存在以下差别:
五、默认的 securityContext 介绍和使用
官方文档:#security-context
SecurityContext 包含 Pod 级别的安全属性和常见的容器设置。 可选:默认为空。每个数组的默认值见类型描述。
【温馨提示】PodSecurityContext 包含 Pod 级别的安全属性和常用容器设置。 一些数组也存在于 container.securityContext 中。container.securityContext 中的数组值优先于 PodSecurityContext 的数组值。
上面只是列举了几个常用的参数,更多参数,可以参考官方文档。对应的数组如下:
【示例1】PodSecurityContext
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:
securityContext:
runAsUser: 10000
runAsGroup: 10000
containers:
- name: nginx
image: nginx:1.15.4
【示例2】container.securityContext
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:
securityContext:
runAsUser: 10000
runAsGroup: 10000
containers:
- name: nginx
image: nginx:1.15.4
securityContext:
runAsUser: 10000
runAsGroup: 10000
privileged: true
fsGroup: 2000
YAML 复制 全屏
如上这个配置,可以看见 Pod 中所有容器内的进程都是已用户 uid=10000 和主组 gid=10000来运行的,而创建的任何文件的属组都是 groups=2000。通过这样的方式,可以达到让用户的进程不使用默认的 Root (uid=0,gid=0)权限的目的。
【温馨提示】镜像中必须储存10000 UID 和 10000 GUI ,如果同时设置了,container.securityContext优先级更高。
K8s PSP 和 securityContext 介绍与简单使用就先到这儿,有任何疑惑欢迎给我留言,后续会持续更新【云原生+大数据】相关的文章。