共計 9219 個字符,預計需要花費 24 分鐘才能閱讀完成。
如何簡化生產中的 Pod 安全策略,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
Pod 安全策略對于強化 K8S 集群安全至關重要。本文將延續之前的文章繼續深入介紹 Pod 安全策略。
首先,簡單介紹了如何將 Pod 與 Pod 安全策略相關聯,并使用 RBAC 來展示具體步驟。然后介紹如何在 Rancher 中啟用默認的 PSP 和創建自定義 PSP。最后將使用一種工具來簡化生產中 Pod 安全策略的使用,極大提升生產力,趕緊戳文咯~
我們有意省略了有關基于角色的訪問控制(RBAC)以及如何將 Pod 與特定 PSP 連接的具體細節。那下面讓我們繼續深入研究 PSP。
將 Pod 與 Pod 安全策略匹配
你可能已經注意到,PSP 模式沒有與任何 Kubernetes 命名空間、Service Account 或 Pod 相關聯。實際上,PSP 是集群范圍的資源。那么,我們如何指定哪些 Pod 應該由哪些 PSP 來管理呢?下圖顯示了所有參與組件、資源以及準入流程的工作方式。
也許一開始聽起來很復雜。現在,我們來詳細介紹一下。
部署 Pod 時,準入控制將根據請求 deployment 的對象來應用策略。
Pod 本身沒有任何關聯的策略——執行該 Deployment 的是 service account。在上圖中,Jorge 使用 webapp-sa service account 部署了 pod。
RoleBinding 將 service account 與 Roles(或 ClusterRoles)相關聯,Role 是指定可以使用 PSP 的資源。在該圖中,webapp-sa 與 webapp-role 關聯,后者為特定的 PSP 資源提供使用許可。部署 Pod 時,將根據 webapp-sa PSP 對 Pod 進行檢查。實際上,一個 service account 可以使用多個 PSP,并且其中一個可以驗證 Pod 就足夠了。你可以在官方文檔中查看詳細信息:
https://kubernetes.io/docs/concepts/policy/pod-security-policy/#policy-order
然后,準入控制將決定 Pod 是否符合其中任何一個 PSP。如果 Pod 符合要求,準入控制將調度 Pod;如果 Pod 不符合規定,則會阻止部署。
以上內容可以總結為以下幾點:
Pod 身份由其 service account 確定
如果規范中未聲明任何 service account,則將使用默認賬戶
你需要允許使用聲明 Role 或 ClusterRole
最后,需要有一個 RoleBinding,它將 Role(從而允許訪問使用 PSP)與 Pod 規范中聲明的 Servcie Account 相關聯。
讓我們用一些例子來說明。
RBAC 的真實示例
假設你已經有一個啟用了 PSP 的集群,這是采用 PSP 創建限制性 PSP 的常用方法,該 PSP 可以被任意 Pod 使用。然后你將添加更為特定的 PSP,該 PSP 有綁定到特定 service account 的其他特權。擁有默認、安全且嚴格的策略有助于集群的管理,因為大多數 Pod 不需要特殊的特權或功能,并且在默認情況下即可運行。然后,如果你的某些工作負載需要其他特權,我們可以創建一個自定義 PSP 并將該工作負載的特定 service account 綁定到限制較少的 PSP。
但是,如何將 Pod 綁定到特定的 PSP 而不是默認的受限 PSP?以及如何使用不自動添加 RoleBindings 的普通 Kubernetes 集群來做到這一點?
讓我們看一個完整的示例,在該示例中,我們定義一些安全的默認值(集群中任何 service account 都可以使用的受限 PSP),然后為需要該服務的特定 deployment 向單個 service account 提供其他特權。
首先,我們手動創建一個新的命名空間。它不會由 Rancher 管理,所以不會自動創建 RoleBindings。然后我們在該命名空間中嘗試部署一個受限的 Pod:
$ kubectl create ns psp-test
$ cat deploy-not-privileged.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: not-privileged-deploy
name: not-privileged-deploy
spec:
replicas: 1
selector:
matchLabels:
app: not-privileged-deploy
template:
metadata:
labels:
app: not-privileged-deploy
spec:
containers:
- image: alpine
name: alpine
stdin: true
tty: true
securityContext:
runAsUser: 1000
runAsGroup: 1000
$ kubectl -n psp-test apply -f deploy-not-privileged.yaml
$ kubectl -n psp-test describe rs
Warning FailedCreate 4s (x12 over 15s) replicaset-controller Error creating: pods not-privileged-deploy-684696d5b5- is forbidden: unable to validate against any pod security policy: []
由于命名空間 psp-test 中沒有 RoleBinding,且該命名空間綁定到允許使用任何 PSP 的角色,因此無法創建 pod。我們將通過創建集群范圍的 ClusterRole 和 ClusterRoleBinding 來解決此問題,以允許任何 Service Account 默認使用受限的 PSP。之前的文章中啟用 PSP 時,Rancher 創建了受限 PSP。
resourceNames:
- restricted-psp
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: restricted-role-bind
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: use-restricted-psp
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts
$ kubectl apply -f clusterrole-use-restricted.yaml
我們應用這些更改之后,非特權 deployment 應正常工作。
但是,如果我們需要部署特權 Pod,則不會被現有策略允許:
$ cat deploy-privileged.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: privileged-sa
namespace: psp-test
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: privileged-deploy
name: privileged-deploy
namespace: psp-test
spec:
replicas: 1
selector:
matchLabels:
app: privileged-deploy
template:
metadata:
labels:
app: privileged-deploy
spec:
containers:
- image: alpine
name: alpine
stdin: true
tty: true
securityContext:
privileged: true
hostPID: true
hostNetwork: true
serviceAccountName: privileged-sa
$ kubectl -n psp-test apply -f deploy-privileged.yaml
$ kubectl -n psp-test describe rs privileged-deploy-7569b9969d
Name: privileged-deploy-7569b9969d
Namespace: default
Selector: app=privileged-deploy,pod-template-hash=7569b9969d
Labels: app=privileged-deploy
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedCreate 4s (x14 over 45s) replicaset-controller Error creating: pods privileged-deploy-7569b9969d- is forbidden: unable to validate against any pod security policy: [spec.securityContext.hostNetwork: Invalid value: true: Host network is not allowed to be used spec.securityContext.hostPID: Invalid value: true: Host PID is not allowed to be used spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
在這種情況下,由于我們創建了 ClusterRoleBinding,所以 Pod 可以使用 PSP,但是 restricted-psp 不會驗證 Pod,因為它需要 privileged、hostNetwork 等參數。
我們已經在前文中看到了 restricted-psp 策略。讓我們檢查一下 default-psp 的細節,這是由 Rancher 在啟用 PSP 允許這些特權時創建的:
$ kubectl get psp default-psp -o yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: *
creationTimestamp: 2020-03-10T08:45:08Z
name: default-psp
resourceVersion: 144774
selfLink: /apis/policy/v1beta1/podsecuritypolicies/default-psp
uid: 1f83b803-bbee-483c-8f66-bfa65feaef56
spec:
allowPrivilegeEscalation: true
allowedCapabilities:
- *
fsGroup:
rule: RunAsAny
hostIPC: true
hostNetwork: true
hostPID: true
hostPorts:
- max: 65535
min: 0
privileged: true
runAsUser:
rule: RunAsAny
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
volumes:
- *
你可以看到這是一個非常寬松的策略,特別是我們允許 privileged、hostNetwork、hostPID、hostIPC、hostPorts 以及以 root 身份運行以及其他功能。
我們只需要明確允許該 Pod 使用 PSP。我們通過創建類似于現有 restricted-clusterrole 的 ClusterRole,但允許使用 default-psp 資源,然后為我們的 psp-test 命名空間創建 RoleBinding 來將 privileged-sa ServiceAccount 綁定到該 ClusterRole:
$ cat clusterrole-use-privileged.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: use-privileged-psp
rules:
- apiGroups: [policy]
resources: [podsecuritypolicies]
verbs: [use]
resourceNames:
- default-psp
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: privileged-role-bind
namespace: psp-test
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: use-privileged-psp
subjects:
- kind: ServiceAccount
name: privileged-sa
$ kubectl -n psp-test apply -f clusterrole-use-privileged.yaml
一會兒之后,特權 Pod 將會被創建。然后你會注意到 restricted-psp 和 default-psp 現在已經可以直接使用。接下來,我們來詳細介紹一下它們。
在 Rancher 上默認的 PSP
在 Rancher 中通過編輯集群設置來啟用 PSP 準入控制,并選擇其中一個已經定義好的 PSP 作為默認選項:
Rancher 將在集群中創建一對 PSP 資源:
restricted-psp:如果你選擇“受限(restricted)”作為默認的 PSP
default-psp:默認的 PSP,允許創建特權 Pod。
除了 restricted-psp 和 default-psp,Rancher 還會創建名為 restricted-clusterrole 的 ClusterRole:
annotations:
serviceaccount.cluster.cattle.io/pod-security: restricted
creationTimestamp: 2020-03-10T08:44:39Z
labels:
cattle.io/creator: norman
name: restricted-clusterrole
rules:
- apiGroups:
- extensions
resourceNames:
- restricted-psp
resources:
- podsecuritypolicies
verbs:
- use
此 ClusterRole 允許使用 restricted-psp 策略。那么 Binding 在何處才可以允許授權使用 pod ServiceAccount 呢?
對于屬于 Rancher 中項目的命名空間,它還在其中為你設置 RoleBinding 配置:
$ kubectl -n default get rolebinding default-default-default-restricted-clusterrole-binding -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
annotations:
podsecuritypolicy.rbac.user.cattle.io/psptpb-role-binding: true
serviceaccount.cluster.cattle.io/pod-security: restricted
labels:
cattle.io/creator: norman
name: default-default-default-restricted-clusterrole-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: restricted-clusterrole
subjects:
- kind: ServiceAccount
name: default
namespace: default
資源名稱(default-default-default-restricted-clusterrole-binding)可能會令人感到困惑,實際上它的構成為:
default-serviceaccountname-namespace-restricted-clusterrole-binding
并且如果你創建一個類似 myserviceaccount 的新的 service account,那么將會自動創建一個新的角色綁定:
$ kubectl create sa myserviceaccount
serviceaccount/myserviceaccount created
$ kubectl get rolebinding
NAME AGE
default-default-default-restricted-clusterrole-binding 13m
default-myserviceaccount-default-restricted-clusterrole-binding 4s
借助這種神奇的功能,你無需為不需要任何提升特權的安全 pod 配置 RBAC。
在 Rancher 中創建你的 PSP
PSP 是一個標準的 Kubernetes 資源,全程是 Pod 安全策略,所以你可以通過 Kubernetes API 或 kubectl CLI 來使用它。
你可以通過在 YAML 文件中定義它們來創建你的自定義 PSP,然后使用 kubectl 在集群中創建資源。查看官方文檔即可了解所有可用控件(https://kubernetes.io/docs/concepts/policy/pod-security-policy/)。在 YAML 中定義了控件集之后,你可以運行:
$ kubectl create psp my-custom-psp
以創建 PSP 資源。
使用 Rancher,你可以從 UI 中直接查看或添加新的策略:
PSP 十分強大,但也十分復雜
配置 Pod 安全策略是一個十分乏味的過程。你在 Kubernetes 集群中啟用 PSP 之后,你想要部署的任意 Pod 都必須經由其中一個 PSP 允許。實施強大的安全策略可能十分耗時,而且為每個應用程序的每個 deployment 生成一個策略也是一種負擔。如果你的策略十分寬松,那么不強制執行最小特權訪問方法;然而,如果它存在很多限制,你可能會破壞你的應用程序,因為 Pod 無法在 Kubernetes 中成功運行。
能夠以最少的訪問要求集自動生成 Pod 安全策略,將幫助你更輕松地安裝 PSP。并且你不能只在生產環境中部署它們,而不驗證你的應用程序是否可以正常工作,而且進行手動測試既繁瑣又效率低下。如果你可以針對 Kubernetes 工作負載的運行時行為驗證 PSP 呢?
如何簡化生產環境中 PSP 的使用?
Kubernetes Pod 安全策略 Advisor(又名 kube-psp-advisor)是一個 Sysdig 的開源工具。kube-psp-advisor 會從 Kubernetes 資源(如 deployment、daemonset、replicaset 等)中掃描現有的安全上下文,將其作為我們想要執行的 reference 模型,然后在整個集群中為所有資源自動生成 Pod 安全策略。kube-psp-advisor 通過查看不同的屬性以創建推薦的 Pod 安全策略:
allowPrivilegeEscalation
allowedCapabilities
allowedHostPaths
hostIPC
hostNetwork
hostPID
Privileged
readOnlyRootFilesystem
runAsUser
Volume
查看 kube-psp-advisor 教程,以獲取有關其工作原理的更多詳細信息:
https://sysdig.com/blog/enable-kubernetes-pod-security-policy/
使用 Sysdig Secure 自動生成 PSP
Sysdig Secure Kubernetes Policy Advisor 可以幫助用戶創建和驗證 Pod 安全策略。
第一步是設置新的 PSP 模擬環境。你可以針對不同范圍內的不同策略(例如 Kubernetes 命名空間)進行多種模擬。
Sysdig 在你的 Deployment 定義中分析 Pod 規范的要求,并為你的應用程序創建權限最小的 PSP。這可以控制是否允許特權 Pod,用戶將其作為容器、volume 等運行。Ni 可以微調 PSP 并針對你將要運行的模擬環境定義命名空間:
左側的策略會破壞應用程序,因為 nginx Deployment 是特權 Pod,并且具有主機網絡訪問權限。你必須決定是擴大 PSP 以允許這種行為,還是選擇減少 Deployment 的特權以適應該策略。無論如何,你在應用 PSP 之前都會檢測到此情況,這會阻止 Pod 運行并在應用程序部署上造成破壞。通過授予或拒絕對特定資源的訪問,PSP 使你可以對在 Kubernetes 中運行的 Pod 和容器進行精細控制。這些策略相對來說容易創建和部署,并且應該是任何 Kubernetes 安全策略的有用組件。
關于如何簡化生產中的 Pod 安全策略問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注丸趣 TV 行業資訊頻道了解更多相關知識。