目錄
例1:基本沒有限制的安全策略,允許創建任意安全設置的Pod。
例2:要求Pod運行用戶爲非特權用戶;禁止提升權限;不允許使用宿主機網絡、端口號、IPC等資源;限制可以使用的Volume類型,等等。
Container-level Security Context
Pod Security Policies(PSP)
Pod Security Policies(PSP)是集羣級的Pod安全策略,自動爲集羣內的Pod和Volume設置Security Context。
使用PSP需要API Server開啓extensions/v1beta1/podsecuritypolicy,並且配置PodSecurityPolicyadmission控制器。
Pod的安全策略配置
Pod 安全策略 是集羣級別的資源,它能夠控制 Pod 運行的行爲,以及它具有訪問什麼的能力。
爲了更精細地控制Pod對資源的使用方式,Kubernetes從1.4版本開始引入了PodSecurityPolicy資源對象對Pod的安全策略進行管理,並在1.10版本中升級爲Beta版,到1.14版本時趨於成熟。
1.PodSecurityPolicy的工作機制
若想啓用PodSecurityPolicy機制,則需要在kube-apiserver服務的啓動參數--enable-admission-plugins中進行設置:
如果是高可用,所有apiserver均需要修改
kubectl edit pod -n kube-system kube-apiserver-k8s-master
--enable-admission-plugins=PodSecurityPolicy
kube-apiserver-k8s-master,值得是你apiserver組件的pod名稱
在開啓PodSecurityPolicy准入控制器後,Kubernetes默認不允許創建任何Pod,需要創建PodSecurityPolicy策略和相應的RBAC授權策略(Authorizing Policies),Pod才能創建成功。
例如,嘗試創建如下Pod:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
使用Kubectl命令創建時,系統將提示“禁止創建”的報錯信息。
接下來創建一個PodSecurityPolicy,配置文件psp-non-privileged.yaml的內容如下:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp-non-privileged
spec:
privileged: false # 不允許特權模式的Pod
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'
之後再次創建Pod既可成功。
上面的PodSecurityPolicy“psp-non-privileged”設置了privileged: false,表示不允許創建特權模式的Pod。
在下面的YAML配置文件pod-privileged.yaml中爲Pod設置了特權模式:
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true
創建Pod時,系統將提示“禁止創建特權模式的Pod”的報錯信息.
2.PodSecurityPolicy配置詳情
在PodSecurityPolicy對象中可以設置下列字段來控制Pod運行時的各種安全策略。
Pod 安全策略 由設置和策略組成,它們能夠控制 Pod 訪問的安全特徵。這些設置分爲如下三類:
- 基於布爾值控制 :這種類型的字段默認爲最嚴格限制的值。
- 基於被允許的值集合控制 :這種類型的字段會與這組值進行對比,以確認值被允許。
- 基於策略控制 :設置項通過一種策略提供的機制來生成該值,這種機制能夠確保指定的值落在被允許的這組值中。
2.1.特權模式相關配置
privileged:是否允許Pod以特權模式運行。
2.2.宿主機資源相關配置
(1)hostPID:是否允許Pod共享宿主機的進程空間。
(2)hostIPC:是否允許Pod共享宿主機的IPC命名空間。
(3)hostNetwork:是否允許Pod使用宿主機網絡的命名空間。
(4)hostPorts:是否允許Pod使用宿主機的端口號,可以通過hostPortRange字段設置允許使用的端口號範圍,以【min,max】設置最小端口號和最大端口號。
(5)Volumes:允許Pod使用的存儲卷Volume類型,設置爲“*”表示允許使用任意Volume類型,建議至少允許Pod使用下列Volume類型。
- configMap
- downwardAPI
- emptyDir
- persistentVolumeClaim
- secret
- projected
(6)AllowedHostPaths:允許Pod使用宿主機的hostPath路徑名稱,可以通過pathPrefix字段設置路徑的前綴,並可以設置是否爲只讀屬性,例子如下。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: allow-hostpath-volumes
spec:
volumes:
- hostPath
allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true
結果爲允許Pod訪問宿主機上以“/foo”爲前綴的路徑,包括“/foo”“/foo/”“/foo/bar”等,但不能訪問“/fool”“/etc/foo”等路徑,也不允許通過“/foo/../”表達式訪問/foo的上層目錄。
(7)FSGroup:設置允許訪問某些Volume的Group ID範圍,可以將規則(rule字段)設置爲MustRunAs、MayRunAs或RunAsAny。
- MustRunAs:需要設置Group ID的範圍,例如1~65535,要求Pod的securityContext.fsGroup設置的值必須屬於該Group ID的範圍。
- MayRunAs:需要設置Group ID的範圍,例如1~65535,不強制要求Pod設置securityContext.fsGroup。
- RunAsAny:不限制Group ID的範圍,任何Group都可以訪問Volume。
(8)ReadOnlyRootFilesystem:要求容器運行的根文件系統(root filesystem)必須是隻讀的。
(9)allowedFlexVolumes:對於類型爲flexVolume的存儲卷,設置允許使用的驅動類型,例子如下。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: allow-flex-volumes
spec:
volumes:
- flexVolume
allowedFlexVolumes:
- driver: example/lvm
- driver: example/cifs
2.3.用戶和組相關配置
(1)RunAsUser:設置運行容器的用戶ID(User ID)範圍,規則字段(rule)的值可以被設置爲MustRunAs、MustRunAsNonRoot或RunAsAny。
- MustRunAs:需要設置User ID的範圍,要求Pod的securityContext.runAsUser設置的值必須屬於該User ID的範圍。
- MustRunAsNonRoot:必須以非root用戶運行容器,要求Pod的securityContext.runAsUser設置一個非0的用戶ID,或者鏡像中在USER字段設置了用戶ID,建議同時設置allowPrivilegeEscalation=false以避免不必要的提升權限操作。
- RunAsAny:不限制User ID的範圍,任何User都可以運行。
(2)RunAsGroup:設置運行容器的Group ID範圍,規則字段的值可以被設置爲MustRunAs、MustRunAsNonRoot或RunAsAny。
- MustRunAs:需要設置Group ID的範圍,要求Pod的securityContext.runAsGroup設置的值必須屬於該Group ID的範圍。
- MustRunAsNonRoot:必須以非root組運行容器,要求Pod的securityContext.runAsUser設置一個非0的用戶ID,或者鏡像中在USER字段設置了用戶ID,建議同時設置allowPrivilegeEscalation=false以避免不必要的提升權限操作。
- RunAsAny:不限制Group ID的範圍,任何Group的用戶都可以運行
(3)SupplementalGroups:設置容器可以額外添加的Group ID範圍,可以將規則(rule字段)設置爲MustRunAs、MayRunAs或RunAsAny。
- MustRunAs:需要設置Group ID的範圍,要求Pod的securityContext.supplementalGroups設置的值必須屬於該Group ID範圍。
- MayRunAs:需要設置Group ID的範圍,不強制要求Pod設置securityContext.supplementalGroups。
- RunAsAny:不限制Group ID的範圍,任何supplementalGroups的用戶都可以運行。
2.4.提升權限相關配置
(1)AllowPrivilegeEscalation:設置容器內的子進程是否可以提升權限,通常在設置非root用戶(MustRunAsNonRoot)時進行設置。
(2)DefaultAllowPrivilegeEscalation:設置AllowPrivilegeEscalation的默認值,設置爲disallow時,管理員還可以顯式設置AllowPrivilegeEscalation來指定是否允許提升權限。
2.5.Linux能力相關配置
(1)AllowedCapabilities:設置容器可以使用的Linux能力列表,設置爲“*”表示允許使用Linux的所有能力(如NET_ADMIN、SYS_TIME等)。
(2)RequiredDropCapabilities:設置不允許容器使用的Linux能力列表。
(3)DefaultAddCapabilities:設置默認爲容器添加的Linux能力列表,例如SYS_TIME等,Docker建議默認設置的Linux能力請查看https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities。
2.6.SELinux相關配置
seLinux:設置SELinux參數,可以將規則字段(rule)的值設置爲MustRunAs或RunAsAny。
- MustRunAs:要求設置seLinuxOptions,系統將對Pod的securityContext.seLinuxOptions設置的值進行校驗。
- RunAsAny:不限制seLinuxOptions的設置。
2.7.其他Linux相關配置
(1)AllowedProcMountTypes:設置允許的ProcMountTypes類型列表,可以設置allowedProcMountTypes或DefaultProcMount。
(2)AppArmor:設置對容器可執行程序的訪問控制權限,詳情請參考https://kubernetes.io/docs/tutorials/clusters/apparmor/#podsecuritypolicy-annotations
(3)Seccomp:設置允許容器使用的系統調用(System Calls)的profile。
(4)Sysctl:設置允許調整的內核參數,詳情請參考https://kubernetes.io/docs/concepts/cluster-administration/sysctl-cluster/#podsecuritypolicy
示例的PodSecurityPolicy安全策略配置
例1:基本沒有限制的安全策略,允許創建任意安全設置的Pod。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: privileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
spec:
privileged: true
allowPrivilegeEscalation: true
allowedCapabilities:
- '*'
volumes:
- '*'
hostNetwork: true
hostPorts:
- min: 0
max: 65535
hostIPC: true
hostPID: true
runAsUser:
rule: 'RunAsAny'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'RunAsAny'
fsGroup:
rule: 'RunAsAny'
例2:要求Pod運行用戶爲非特權用戶;禁止提升權限;不允許使用宿主機網絡、端口號、IPC等資源;限制可以使用的Volume類型,等等。
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'
apparmor.security.beta.kubernetes.io/dafaultProfileName: 'runtime/default'
spec:
privileged: false
allowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'configMap'
- 'emptyDir'
- 'projected'
- 'secret'
- 'downwardAPI'
- 'persistentVolumeClaim'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
fsGroup:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
readOnlyRootFilesystem: false
分配Kubernetes Pod安全策略
Kubernetes建議使用RBAC授權機制來設置針對Pod安全策略的授權,通常應該對Pod的ServiceAccount進行授權。
角色的訪問控制(RBAC)是kubernetes標準的授權模式,並且很容應用於Pod安全策略。藉助RBAC,你可以將Pod安全策略分配給應用。
爲此,我們將創建一個新的YAML文件,該文件不僅會創建集羣範圍的角色(使用ClusterRole定義),還將創建集羣綁定(使用ClusterRoleBinding定義),以向每個經過身份驗證的用戶授予訪問權限。
例如,可以創建如下ClusterRole(也可以創建Role)並將其設置爲允許使用PodSecurityPolicy:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: <role name>
rules:
- apiGroup: ['policy']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames:
- <list of policies to authorize> # 允許使用的PodSecurityPolicy列表
然後創建一個ClusterRoleBinding與用戶和ServiceAccount進行綁定:
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: <binding name>
roleRef:
kind: ClusterRole
name: <roke name> # 之前創建的ClusterRole名稱
apiGroup: rbac.authorization.k8s.io
subjects:
# 對特定Namespace中的ServiceAccount進行授權
- kind: ServiceAccount
name: <authorized servie account name> # ServiceAccount 的名稱
namespace: <authorized pod namespace> # Namespace的名稱
# 對特定用戶進行授權(不推薦)
- kind: User
apiGroup: rbac.authorization.k8s.io
name: <authorized user name> # 用戶名
也可以創建RoleBinding對與該RoleBinding相同的Namespace中的Pod進行授權,通常可以與某個系統級別的Group關聯配置,例如:
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: <binding name>
namespace: <binding namespace> # 該RoleBinding 所屬的Namespace
roleRef:
kind: Role
name: <role name>
apiGroup: rbac.authorization.k8s.io
subjects:
# 授權該Namespace中的全部ServiceAccount
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:serviceaccounts
# 授權該Namespace中的全部哦用戶
- kind: Group
apiGroup: rbac.authorization.k8s.io
name: system:authenticated
Security Context
通過上文,我們瞭解了PodSecurityPolicy策略,知道了
- 在系統管理員對Kubernetes集羣中設置了PodSecurityPolicy策略之後,系統將對Pod和Container級別的安全設置進行校驗,對於不滿足PodSecurityPolicy安全策略的Pod,系統將拒絕創建。
但除此之外還有個,securityContext
- Pod和容器的安全策略可以在Pod或Container的securityContext字段中進行設置,如果在Pod和Container級別都設置了相同的安全類型字段,容器將使用Container級別的設置。
Security Context的目的是限制不可信容器的行爲,保護系統和其他容器不受其影響。
要爲Pod指定安全設置,請securityContext
在Pod規範中包括該字段。該securityContext
字段是 PodSecurityContext對象。
Kubernetes提供了三種配置Security Context的方法:
- Container-level Security Context:僅應用到指定的容器
- Pod-level Security Context:應用到Pod內所有容器以及Volume
- Pod Security Policies(PSP):應用到集羣內部所有Pod以及Volume
Container-level Security Context
Container-level Security Context僅應用到指定的容器上,並且不會影響Volume。
Container級別可以設置的安全策略類型
- runAsUser:容器內運行程序的用戶ID。
- runAsGroup:容器內運行程序的用戶組ID。
- runAsNonRoot:是否必須以非root用戶運行程序。
- privileged:是否以特權模式運行。
- allowPrivilegeEscalation:是否允許提升權限。
- readOnlyRootFilesystem:根文件系統是否爲只讀屬性。
- capabilities:Linux能力列表。
- seLinuxOptions:SELinux相關設置。
比如
例1:Container級別的安全設置,作用於特定的容器。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-2
spec:
securityContext:
runAsUser: 1000
containers:
- name: sec-ctx-demo-2
image: tomcat
securityContext:
runAsUser: 2000
allowPrivilegeEscalation: false
創建該Pod之後進入容器環境,查看到運行進程的用戶ID爲2000:
例2:爲Container設置可用的Linux能力,爲容器設置允許使用的Linux能力包括NET_ADMIN和SYS_TIME。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-3
spec:
containers:
- name: sec-ctx-3
image: tomcat
securityContext:
capabilities:
add: ["NET_ADMIN","SYS_TIME"]
創建該Pod之後進入容器環境,查看1號進程的Linux能力設置:
Pod-level Security Context
Pod-level Security Context應用到Pod內所有容器,並且還會影響Volume(包括fsGroup和selinuxOptions)。
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: tomcat
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
securityContext:
allowPrivilegeEscalation: false
在spec.securityContext中設置瞭如下參數。
- runAsUser=1000:所有容器都將以User ID 1000運行程序,所有新生成文件的User ID也被設置爲1000。
- runAsGroup=3000:所有容器都將以Group ID 3000運行程序,所有新生成文件的Group ID也被設置爲3000。
- fsGroup=2000:掛載的卷“/data/demo”及其中創建的文件都將屬於Group ID 2000。
- 創建該Pod之後進入容器環境,查看到運行進程的用戶ID爲1000:
- 查看從Volume掛載到容器的/data/demo目錄,其Group ID爲2000
- 在該目錄下創建一個新文件,可見其用戶ID爲1000,組ID爲2000:
Pod級別可以設置的安全策略類型
- runAsUser:容器內運行程序的用戶ID。
- runAsGroup:容器內運行程序的用戶組ID。
- runAsNonRoot:是否必須以非root用戶運行程序。
- fsGroup:SELinux相關設置。
- seLinuxOptions:SELinux相關設置。
- supplementalGroups:允許容器使用的其他用戶組ID。
- sysctls:設置允許調整的內核參數。
參考鏈接:
https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
https://kubernetes.io/zh/docs/concepts/policy/pod-security-policy/
https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.18/#securitycontext-v1-core