k8s篇之Pod 安全策略

文章目录

  • 前言
  • 什么是 Pod 安全策略?
  • 许可控制
  • 开启
  • 操作Pod 安全策略
    • 创建 Pod 安全策略
    • 获取 Pod 安全策略列表
    • 修改 Pod 安全策略
    • 删除 Pod 安全策略
    • 根据安全策略创建pod
  • PodSecurityPolicy配置详解
    • 特权模式相关配置
    • 宿主机资源相关配置
    • 用户和组相关配置
    • 提升权限相关配置
    • Linux能力相关配置
    • SELinux相关配置
    • 其它Linux相关配置
    • 常用的PodSecurityPolicy安全策略配置
    • Pod的安全设置详解


前言

默认情况下,Kubernetes 允许创建一个有特权容器的 Pod,这些容器很可能会危机系统安全,而 Pod 安全策略(PSP)则通过确保请求者有权限按配置来创建 Pod,从而来保护集群免受特权 Pod 的影响。

为了更精细地控制Pod对资源的使用方式,Kubernetes从1.4版本开始引入了PodSecurityPolicy资源对象对Pod的安全策略进行管理。

PodSecurityPolicy 是 Kubernetes API 对象,你可以在不对 Kubernetes 进行任何修改的情况下创建它们,但是,默认情况下不会强制执行我们创建的一些策略,我们需要一个准入控制器、kube-controller-manager 配置以及 RBAC 权限配置。

PodSecurityPolicy 类型的对象能够控制,是否可以向 Pod 发送请求,该 Pod 能够影响被应用到 Pod 和容器的 SecurityContext。


什么是 Pod 安全策略?

Pod 安全策略 是集群级别的资源,它能够控制 Pod 运行的行为,以及它具有访问什么的能力。 PodSecurityPolicy 对象定义了一组Pod运行时必须遵循的条件及相关字段的默认值,只有 Pod 满足这些条件才会被系统接受。 它们允许管理员控制如下方面:

控制面 字段名称
特权容器 privileged
使用宿主名字空间 hostPID,hostIPC
使用宿主的网络和端口 hostNetwork,hostPorts
控制卷类型的使用 wolumes
使用宿主文件系统 allowHostPaths
允许使用特定的FlesVolume驱动 allowFlexVolumes
分配拥有Pod卷的FSGroup fsGroup
以只读的方式访问根文件系统 readOnlyRootFilesystem
设置容器的用户和组ID runAsUser,runAsGroup,supplementalGroups
限制root账号特提升 allowPrivilegeEscalation,defaultAllowPrivateEscalation
设置容器的 SELinux 上下文 seLinux
指定容器可以挂载的proc类型 alloweProcMountTypes
指定容器使用的AppArmor模板 annotations
指定容器使用的seccomp annotations
指定容器使用的sysctl模板 forbiddenSysctls,allowedUnsafeSysctls

Pod 安全策略 由设置和策略组成,它们能够控制 Pod 访问的安全特征。这些设置分为如下三类:

  • 基于布尔值控制 :这种类型的字段默认为最严格限制的值
  • 基于被允许的值集合控制 :这种类型的字段会与这组值进行对比,以确认值被允许
  • 基于策略控制 :设置项通过一种策略提供的机制来生成该值,这种机制能够确保指定的值落在被允许的这组值中。

许可控制

包含 PodSecurityPolicy 的 许可控制,允许控制集群资源的创建和修改,基于这些资源在集群范围内被许可的能力。

许可使用如下的方式为 Pod 创建最终的安全上下文:

  • 检索所有可用的 PSP。
  • 生成在请求中没有指定的安全上下文设置的字段值。
  • 基于可用的策略,验证最终的设置。

如果某个策略能够匹配上,该 Pod 就被接受。如果请求与 PSP 不匹配,则 Pod 被拒绝。

Pod 必须基于 PSP 验证每个字段。

开启

如果需要开启PodSecurityPolicy,需要在kube-apiserver的启动参数中设置如下参数

--enable-admission-plugins=PodSecurityPolicy

在开启PodSecurityPolicy准入控制器后,k8s默认不允许创建任何Pod,需要创建PodSecurityPolicy和RBAC授权策略,Pod才能创建成功。

注:修改kube-apiserver配置文件/etc/kubernetes/manifests/kube-apiserver.yaml,由于是static
pod,所以修改就会生效。

系统默认此参数为:

--enable-admission-plugins=NodeRestriction

操作Pod 安全策略

创建PodSecurityPolicy对象之后,就可以成功创建pod资源了

创建 Pod 安全策略

下列PodSecurityPolicy表示是不允许创建特权模式的Pod

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 安全策略列表

获取已存在策略列表,使用 kubectl get:

$ kubectl get psp
NAME        PRIV   CAPS  SELINUX   RUNASUSER         FSGROUP   SUPGROUP  READONLYROOTFS  VOLUMES
permissive  false  []    RunAsAny  RunAsAny          RunAsAny  RunAsAny  false           [*]
privileged  true   []    RunAsAny  RunAsAny          RunAsAny  RunAsAny  false           [*]
restricted  false  []    RunAsAny  MustRunAsNonRoot  RunAsAny  RunAsAny  false           [emptyDir secret downwardAPI configMap persistentVolumeClaim projected]

修改 Pod 安全策略

通过交互方式修改策略,使用 kubectl edit:

$ kubectl edit psp permissive

该命令将打开一个默认文本编辑器,在这里能够修改策略。

删除 Pod 安全策略

一旦不再需要一个策略,很容易通过 kubectl 删除它:

$ kubectl delete psp permissive
podsecuritypolicy "permissive" deleted

根据安全策略创建pod

上面的PodSecurytiPolicy是设置了不允许创建特权模式的Pod,例如,在下面的YAML配置文件pod-privileged.yaml中为Pod设置了特权模式:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    ports:
    - containerPort: 80
    securityContext:
      privileged: true

创建的时候会报如下错误:

unable to validate against any pod security policy

PodSecurityPolicy配置详解

在PodSecurityPolicy对象中可以设置下列字段来控制Pod运行时的各种安全策略

特权模式相关配置

  • privileged:是否允许Pod以特权模式运行

宿主机资源相关配置

  • hostPID:是否允许Pod共享宿主机的进程空间
  • hostIPC:是否允许Pod共享宿主机的IPC命名空间
  • hostNetwork:是否允许Pod共享宿主机网络的命名空间
  • hostPorts:是否允许Pod使用宿主机的端口号,可以通过hostPortRange字段设置允许使用的端口号范围,以[min, max]设置最小端口号和最大端口号
  • Volumes:允许Pod使用的存储卷Volume类型,设置为“*”表示允许使用任意Volume类型,建议至少允许Pod使用下列Volume类型。configMap,emptyDir、downwardAPI、persistentVolumeClaim、secret、projected
  • AllowedHostPaths:允许Pod使用宿主机的hostPath路径名称,可通过pathPrefix字段设置路径的前缀,并可以设置是否只读属性,例如:只允许Pod访问宿主机上以“/foo”为前缀的路径,包 括“/foo”“/foo/”“/foo/bar”等,
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: all-hostpath-volumes
spec:
  volumes:
 - hostPath
  allowedHostPaths:
 - pathPrefix: "/foo"
    readOnly: true   
  • FSGroup:设置允许访问某些Volume的Group ID范围,可以将rule字段设置为ManyRunAs、MayRunAs、RunAsAny
    • MustRunAs:需要设置Group ID的范围,例如1~65535,要求Pod的securityContext.fsGroup设置的值必须属于该Group ID的范围。
  • ReadOnlyRootFilesystem:要求容器运行的根文件系统(root filesystem)必须是只读的
  • allowedFlexVolumes:对于类型为flexVolume的存储卷,设置允许使用的驱动类型,例如:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: allowedflexvolumes
spec:
  volumes:
 - flexVolume
  allowedFlexVolumes:
 - driver: example/lvm
 - driver: example/cifs

用户和组相关配置

  • RunAsUser:设置运行容器的用户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都可以运行。
  • 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的用户都可以运行。
  • 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的用户都可以运行。

提升权限相关配置

  • AllowPrivilegeEscalation:用于设置容器内的子进程是否可以提升权限,通常在设置非Root用户(MustRunAsNonRoot)时进行设置。
  • DefaultAllowPrivilegeEscalation:设置AllowPrivilegeEscalation的默认值,设置为disallow时,管理员还可以显式设置 AllowPrivilegeEscalation来指定是否允许提升权限。

Linux能力相关配置

  • AllowedCapabilities:设置容器使用的linux能力列表,设置为“*”表示允许使用Linux的所有能力(如NET_ADMIN、SYS_TIME等)。
  • RequiredDropCapabilities:设置不允许容器使用的linux能力列表
  • DefaultAddCapabilities:设置默认为容器添加的Linux能力列表,例如SYS_TIME等

SELinux相关配置

  • seLinux:设置SELinux参数,可以将规则字段(rule)的值设置为MustRunAs或RunAsAny。
  • MustRunAs:要求设置seLinuxOptions,系统将对Pod的securityContext.seLinuxOptions设置的值进行校验。
  • RunAsAny:不限制seLinuxOptions的设置

其它Linux相关配置

  • AllowedProcMountType:设置允许的PropMountTypes类型列表,可以设置allowedProcMountTypes或DefaultProcMount。
  • AppArmor:设置对容器可执行程序的访问控制权限
  • Seccomp:设置允许容器使用的系统调用(System Calls)的profile
  • Sysctl:设置允许调整的内核参数

常用的PodSecurityPolicy安全策略配置

1.基本没有限制的安全策略,允许创建任意安全设置的Pod。

apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: privileged
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: "*"
spec:
  privileged: true  #不允许创建特权模式的Pod
  allowPrivilegeEscalation: true  #设置子进程是否可以提升权限,配置MustRunAsNonRoot
  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: retricted
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
    seccomp.security.alpha.kubernetes.io/defaultProfileNames: 'docker/default'
    apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default' 
    apparmor.security.beta.kubernetes.io/defaultProfileNames: '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: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAsRoot'
    ranges:
    - min: 1
      max: 65535
  fsGroup:
    rule: 'MustRunAsRoot'
    ranges:
    - min: 1
      max: 65535
  readOnlyRootFilesystem: false

Kubernetes建议使用RBAC授权机制来设置针对Pod安全策略的授权,通常应该对Pod的ServiceAccount进行授权。

例如,可以创建如下ClusterRole(也可以创建Role)并将其设置为允许使用PodSecurityPolicy:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: role-name
rules:
- apiGroups: ['policy']
  resources: ['podsecuritypolicies']
  verbs: ['use']
  resourceNames:
  - #允许使用的PodSecurityPolicy列表

然后创建一个ClusterRoleBinding与用户和ServiceAccount进行绑定

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: bind-name
ruleRef:
  kind: ClusterRole
  name: role-name
  apiGroup: rabc.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: serviceaccount
  namespace:
- kind: User
  name: username
  apiGroup: rbac.authorization.k8s.io

也可以创建RoleBinding对与该RoleBinding相同的Namespace中的Pod进行授权,通常可以与某个系统级别的Group关联配置,例如:

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: bind-name
  namespace: namespace #该RoleBinding所属的namespace
roleRef:
  kind: Role
  name: 
  apiGroup: rabc.authorization.k8s.io
subjects:
#授权该Namespace中的全部ServiceAccount
- kind: Group
  apiGroup: rabc.authorization.k8s.io
  name: system:serviceaccounts
#授权该Namespace的全部用户
- kind: User
  apiGroup: rabc.authorization.k8s.io
  name: system:authenticated

Pod的安全设置详解

Pod和容器的安全策略可以在Pod或Container的securityContext字段中设置,如果在Pod和Container级别都设置了相同的安全类型字段,容器将使用Container级别的设置。

在Pod级别可以设置的安全措施如下:
runAsUser:容器内运行程序的用户ID。

  • runAsGroup:容器内运行程序的用户组ID。
  • runAsNonRoot:是否必须以非root用户运行程序。◎ fsGroup:SELinux相关设置。
  • seLinuxOptions:SELinux相关设置。
  • supplementalGroups:允许容器使用的其他用户组ID。
  • sysctls:设置允许调整的内核参数。
  • 在Container级别可以设置的安全策略类型如下:
  • runAsUser:容器内运行程序的用户ID。
  • runAsGroup:容器内运行程序的用户组ID。
  • runAsNonRoot:是否必须以非root用户运行程序。
  • privileged:是否以特权模式运行。
  • allowPrivilegeEscalation:是否允许提升权限。
  • readOnlyRootFilesystem:根文件系统是否为只读属性。
  • capabilities:Linux能力列表。
  • seLinuxOptions:SELinux相关设置。

例如:Pod级别的安全设置,作用于该Pod内的全部容器

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: nginx
    volumeMounts:
    - name: sec-ctx-demo
      mountPath: /data/demo
    securityContext:
      allowPrivilegeEscalation: false
  • runAsUser=1000:所有容器都将以User ID 1000运行程序,所有新生成文件的User ID也被设置为1000。
  • runAsGroup=3000:所有容器都将以Group ID 3000运行程序,所有新生成文件的Group ID也被设置为3000。
  • fsGroup=2000:挂载的卷“/data/demo”及其中创建的文件都将属于Group ID 2000。

Container级别的安全设置,作用于特定的容器。

apiVersion: v1
kind: Pod
metadata:
  name: scd-2
spec:
  securityContext:
    runAsUser: 1000
  containers:
  - name: scd-2
    image: nginx:latest
    imagePullPolicy: IfNotPresent
    securityContext:
      runAsUser: 2000
      allowPrivilegeEscalation: false

为Container设置可用的Linux能力,为容器设置允许使用的Linux能力包括NET_ADMIN和SYS_TIME。

apiVersion: v1
kind: Pod
metadata:
  name: scd-3
spec:
  containers:
  - name: scd-3
    image: nginx
    securityContext:
      capabilities:
        add: ["NET_ADMIN","SYS_TIME"]

你可能感兴趣的:(#,kubernetes,kubernetes,docker,云原生,服务器,面试)