安全策略
3 分钟阅读
简要概述
本节包含对 Kubernetes 集群环境安全的各种策略建议。
服务账户与RBAC
确保角色 cluster-admin 仅在需要时使用
Kubernetes 提供了一组默认的 RBAC 权限策略,其中 cluster-admin
允许用户访问任何资源以执行任何操作。
# kubectl get clusterrole cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: "2023-10-07T03:47:13Z"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: cluster-admin
resourceVersion: "23814649"
uid: 49271b7e-1864-425b-b8dc-8b3900955d03
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
- nonResourceURLs:
- '*'
verbs:
- '*'
# ^C
获取哪些用户绑定了 cluster-admin
角色列表:
kubectl get clusterrolebindings -o=custom-columns=NAME:.metadata.name,ROLE:.roleRef.name,SUBJECT:.subjects[*].name
确保最小化权限访问 Secret 资源
通过以下指令审查:
kubectl get roles --all-namespaces -o yaml
kubectl get clusterroles -o yaml
TODO;
确保最小化通配符在 Roles 与 ClusterRoles 使用
同上。
确保最小化用户创建 Pod 的能力
在集群中创建 Pod 的能力可以提供许多权限提升的机会,例如为这些 Pod 分配特权服务帐户,或挂载可访问敏感数据的hostPaths(除非实施了Pod安全策略来限制这种访问)
通过以上方式审查。
确保访问 Kubernetes API 的工作负载都使用特定服务帐户
Kubernetes 提供了一个默认的服务帐户 “default”,当创建的 Pod 非分配特定的服务帐户,将会关联使用它。
如果需要从 Pod 访问 Kubernetes API,则应为该 Pod 创建一个特定的服务帐户,并将权限授予该服务帐户,不应使用默认服务帐户来授予应用程序的权限,这样可以更容易地进行审核和审查。
默认服务帐户应配置为不提供服务帐户令牌,也不具有任何明确的权限分配。
可通过以下两种方式关闭服务账户挂载:
- 在 Pod 模版中设置 “automountServiceAccountToken: false”
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/kube-image-repo/busybox:1.35.0
name: nginx
args:
- /bin/sh
- -c
- "sleep 3600"
automountServiceAccountToken: false
- 在创建 Service Account 中设置 “automountServiceAccountToken: false” 明确关闭
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx
automountServiceAccountToken: false
如果未关闭,服务账户授权会被挂载在容器以下位置:
/var/run/secrets/kubernetes.io/serviceaccount # df -h
Filesystem Size Used Available Use% Mounted on
tmpfs 7.3G 12.0K 7.3G 0% /var/run/secrets/kubernetes.io/serviceaccount
......
/var/run/secrets/kubernetes.io/serviceaccount #
/var/run/secrets/kubernetes.io/serviceaccount # ls
ca.crt namespace token
/var/run/secrets/kubernetes.io/serviceaccount # ^C
确保不使用 system:masters 用户组
用户组 “system:masters” 是硬编码在 k8s 源码里面作为公知组,拥有集群管理员权限,避免在授权中直接使用。
# kubectl get clusterrolebinding cluster-admin -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: "2023-10-07T03:47:13Z"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: cluster-admin
resourceVersion: "23814711"
uid: 35e25988-3032-40a6-999f-34c78fd36963
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:masters
# ^C
确保限制使用 Bind Impersonate Escalate 权限
TODO;
Pod 安全策略
确保至少存在一个活跃的策略控制机制
Pod 安全策略由两种方式:
- 基于 k8s 树内的 Pod Security Admission 控制器实现;
- 基于外部的访问控制系统通过 validation 与 mutation webhooks 实现。
确保至少使用其中一种,如果没有的话,以下这些敏感操作将无法被限制:
- 特权容器;
- 挂载 hostPath。
确保没用使用特权容器
对以下三个属性设置为 “true” 开启特权容器运行。
spec.containers[].securityContext.privileged: true
spec.initContainers[].securityContext.privileged: true
spec.ephemeralContainers[].securityContext.privileged: true
这里启动一个 pod 为特权容器:
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/kube-image-repo/busybox:1.35.0
name: nginx
args:
- /bin/sh
- -c
- "sleep 3600"
securityContext:
privileged: true
特权容器可以访问所有Linux内核功能和设备。以完全权限运行的容器几乎可以完成主机所能做的一切。此标志的存在是为了允许特殊的用例,如操作网络堆栈和访问设备。
确保最大限度地减少 hostPID 命名空间使用
通过添加 spec.hostPID: true
开启共享宿主进程命名空间,此时在容器内可以观察到宿主上所有运行的进程。
这是一个建议示列配置:
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/kube-image-repo/busybox:1.35.0
name: nginx
args:
- /bin/sh
- -c
- "sleep 3600"
hostPID: false
确保最大限度地减少 hostIPC 命名空间使用
通过添加 spec.hostIPC: true
开启共享宿主进程间通信命名空间,此时在容器内可以与宿主上其他进程通过管道、套接字、消息队列、信号量等通讯。
这是一个建议示列配置:
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/kube-image-repo/busybox:1.35.0
name: nginx
args:
- /bin/sh
- -c
- "sleep 3600"
hostICP: false
确保最大限度地减少 hostNetwork 命名空间使用
通过添加 spec.hostNetwork: true
开启共享宿主网络命名空间,此时在容器内使用同宿主网络IP、监听端口、数据流量等。
这是一个建议示列配置:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/kube-image-repo/busybox:1.35.0
name: nginx
args:
- /bin/sh
- -c
- "sleep 3600"
hostNetwork: false
确保避免容器子进程可以获得比父进程更高的权限
在配置了 spec.securityContext.allowPrivilegeEscalation: true
情况下运行的容器有可能存在具有比父进程更高的权限。
这是一个建议示列配置:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/kube-image-repo/busybox:1.35.0
name: nginx
args:
- /bin/sh
- -c
- "sleep 3600"
securityContext:
allowPrivilegeEscalation: false
确保不使用 root 用户运行容器
容器可以以任何用户运行,虽然有运行时安全策略防护,在处于 root 运行的容器还是比普通用户更容器被攻破。
这是一个建议示列配置:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: registry.cn-hangzhou.aliyuncs.com/kube-image-repo/busybox:1.35.0
name: nginx
args:
- /bin/sh
- -c
- "sleep 3600"
securityContext:
runAsNonRoot: false
runAsUser: 65534
确保容器没有 NET_RAW 能力
TODO;
确保最小化 windows 容器没有 HostProcess 权限
TODO;
确保最小化使用 HostPath 挂载存储卷
通过 hostPath 的容器可以访问底层集群节点的文件系统,可以允许容器访问宿主上文件系统的任意区域,如:/etc/passwd。
所以必须存在策略限制挂载的路径。
确保避免使用 HostPorts 开放容器端口
主机端口将容器直接连接到宿主的网络,这可以绕过诸如网络策略之类的控制。
网络策略与 CNI
建议使用的 CNI 支持网络策略
TODO;
建议为命名空间定义默认网络策略
TODO;
kubectl get networkpolicy --all-namespaces
资源 Secrets 管理
建议机密数据作为文件挂载优先于环境变量
应用程序代码配置使用环境是相当常见,这将包括作为环境变量传递的任何机密值,这样任何有权访问日志的用户或应用都可以观察该值。
通过以下指令可以获取使用了环境变量:
kubectl get all -o jsonpath='{range .items[?(@..secretKeyRef)]} {.kind} {.metadata.name} {"\n"}{end}' -A
建议使用外部机密数据管理系统
如果您有更复杂的秘密管理需求,请考虑使用外部秘密存储和管理系统,而不是直接使用Kubernetes secrets。确保该解决方案需要身份验证才能访问机密,对机密的访问和使用进行审核,并对机密进行加密。某些解决方案还可以更容易地轮换机密。
因为默认 secrets 使用 base64 加密存储,这样只要集群管理人员拥有权限则可以对数据进行解密。
扩展准入控制器
建议使用 ImagePolicyWebhook 控制器
TODO;
一般公共策略
通过命名空间在资源之间创建管理边界
针对不同业务通过命名空间隔离,限制用户权限范围可以减少错误或恶意活动的影响。Kubernetes 命名空间允许您将创建的资源划分为逻辑命名的组,在一个命名空间中创建的资源可以对其他命名空间隐藏,您可以创建其他名称空间,并将资源和用户附加到这些名称空间。
默认存在以下命名空间:
- “default” 当应用未主动配置部署的 “namespace” 时使用;
- “kube-system” 集群系统应用;
- “kube-node-lease” 维持主机心跳;
- “kube-public” 集群公共信息;
例如在实际使用中可根据需求自定义了以下空间:
- “cloud-monitor” 监控类业务部署;
- “dcim-system” 运维类服务部署;
- “biz-dev-uptime” 业务类开发部署;
确保启动 seccomp profile
TODO;
确保配置 Security Context 在 POD 与 Containers 中
TODO;
确保默认命名空间 default 没有正式应用
kubectl get pods -n default