当前位置: 首页 > 科技观察

如何优雅地为KubernetesPod启用安全策略

时间:2023-03-18 14:38:45 科技观察

本文的演示和示例均在v1.18.17集群中验证。PodSecurityPoliciesPodSecurityPolicies(以下简称psp或podsecuritypolicy)是集群级别的全局资源,可以对pod的创建和更新进行细粒度的授权控制。具体来说,psp对象定义了一组安全条件,pod的spec字段必须满足这些条件才能使其创建或更新请求被apiserver接受。请参阅文档what-is-a-pod-security-policy[1]了解特定的pod字段和安全条件。启用Pod安全策略Kubernetes默认不启用Pod安全策略功能。在集群中启用Pod安全策略的步骤大致分为三步:授予用户对安全策略资源的访问权限,通常是整个命名空间的服务帐户。在集群中创建指定的安全策略资源。为apiserver启用准入控制器插件。请注意,步骤1、2的顺序并不重要,因为它们没有实际效果。但是步骤3建议在最后一步执行,否则一旦启用admission-controller插件,如果集群中没有可用的pod安全策略或者安全策略资源没有预授权,所有的pod创建会被拒绝,包括kube-systemnamespace下的apiserver等系统管理组件(但因为是kubelet管理的静态pod,所以容器还是会运行)。RBAC身份验证创建一个可以访问所有安全策略资源的ClusterRole:apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRolemetadata:name:all-psprules:-apiGroups:['policy']resources:['podsecuritypolicies']verbs:['use']通过ClusterRoleBinding将创建的角色绑定到指定命名空间下的所有服务账号(也可以授权给指定的sa或用户):apiVersion:rbac.authorization.k8s.io/v1kind:ClusterRoleBindingmetadata:name:cluster-psp-bindroleRef:kind:ClusterRolename:all-pspapiGroup:rbac.authorization.k8s.iosubjects:#授权给指定命名空间下的所有服务账户(推荐做法):-kind:GroupapiGroup:rbac.authorization。k8s.io名称:系统:节点名称空间:kube-system-kind:GroupapiGroup:rbac.authorization.k8s.io名称:system:serviceaccounts:kube-system-kind:GroupapiGroup:rbac.authorization.k8s.io名称:system:serviceaccounts:security-test#也可以授权给指定的服务账号或用户(不推荐):-kind:ServiceAccountname:namespace:-kind:UserapiGroup:rbac。授权.k8s.ioname:#授权给所有服务账户:-kind:GroupapiGroup:rbac.authorization.k8s.ioname:system:serviceaccounts#授权给所有经过身份验证的用户:-kind:GroupapiGroup:rbac.authorization.k8s.ioname:system:authenticated创建安全策略资源在集群中创建PodSecurityPolicy资源宽松权限版本:apiVersion:policy/v1beta1kind:PodSecurityPolicymetadata:name:privilegedannotations:seccomp.security.alpha.kubernetes.io/allowedProfileNames:'*'spec:privileged:trueallowPrivilegeEscalation:trueallowedCapabilities:-'*'volumes:-'*'hostNetwork:truehostPorts:-min:0max:65535hostIPC:truehostPID:truerunAsUser:rule:'RunAsAny'seLinux:rule:'RunAsAny'supplementalGroups:rule:'RunAsAny'fsGroup:rule:'RunAsAny'严格权限版本:apiVersion:policy/v1beta1kind:PodSecurityPolicymetadata:name:restrictedannotations:seccomp.security.alpha.kubernetes.io/allowedProfileNames:'docker/default,runtime/default'apparmor.security.beta.kubernetes.io/allowedProfileNames:'runtime/default'apparmor.security.beta.kubernetes.io/defaultProfileName:'runtime/default'spec:privileged:false#需要防止升级到root。allowPrivilegeEscalation:falserequiredDropCapabilities:-ALL#允许核心卷类型.volumes:-'configMap'-'emptyDir'-'projected'-'secret'-'downwardAPI'#假设集群管理员设置的临时CSI驱动程序和持久卷可以安全使用。-'csi'-'persistentVolumeClaim'-'ephemeral'hostNetwork:falsehostIPC:falsehostPID:falserunAsUser:#要求容器在没有root权限的情况下运行。rule:'MustRunAsNonRoot'seLinux:#该策略假定节点使用AppArmor而不是SELinux。rule:'RunAsAny'supplementalGroups:rule:'MustRunAs'ranges:#禁止添加根组。-min:1max:65535fsGroup:rule:'MustRunAs'ranges:#禁止添加根组。-min:1max:65535readOnlyRootFilesystem:false启用admissioncontrollerplugin启用admissioncontrollerpsp插件有两种方式:在现有集群中,修改apiserver的静态清单文件,添加启动参数enable-admission-plugins=PodSecurityPolicy到apiserver。kubelet将自动检测更改并重新启动apiserver。以下示例使用sed替换原始参数:yaml或在初始化集群时向kubeadm配置文件添加额外的参数。apiVersion:kubeadm.k8s.io/v1beta2kind:ClusterConfigurationapiServer:extraArgs:enable-admission-plugins:"PodSecurityPolicy"验证psp的安全限制我们在上面授权的security-test命名空间中进行测试,验证psp对pod的限制。首先确保集群中应用了严格版本的psp资源,然后通过deployment尝试创建一个需要使用hostNetwork的pod:apiVersion:apps/v1kind:Deploymentmetadata:name:nginx-hostnetworkspec:selector:matchLabels:run:nginxtemplate:metadata:labels:run:nginxspec:hostNetwork:truecontainers:-image:nginximagePullPolicy:Alwaysname:nginx-privileged创建并查看结果:$kubectlcreate-fhostnetwork-pod.yaml-nsecurity-testdeployment.apps/nginx-hostnetwork已创建$kubectlgetdeploy-nsecurity-testnginx-hostnetworkNAMEREADYUP-TO-DATEAVAILABLEAGEEnginx-hostnetwork0/10017s$kubectl-nsecurity-testgetevent|grep“podsecuritypolicy”103sWarningFailedCreatedeployment/nginx-hostnetwork错误创建:pods“nginx-hostnetwork-”被禁止:无法验证任何pod安全策略:[spec.securityContext.hostNetwork:无效值:true:Hostnetworkisnotallowedtobeuse]Limitations如果pod违反了安全策略,解决办法要么调整pod规范,要么修改pod安全策略资源psp资源全局有效,不能为不同的namespace设置不同的安全政策层面,这是一个明显的局限性。另外,psp的授权机制也比较复杂。如果没有授权或者没有创建安全策略,结果就是所有的pod都被拒绝,这也导致集群默认开启这个特性很困难。从Kubernetesv1.21开始,PodSecurityPolicy将被弃用,并将在v1.25中删除。Kubernetes引入了PodSecurityAdmission作为其替代,我们将在下面详细说明。WhyPodSecurityAdmissionshouldreplacepspKEP-2579[2]阐述了使用PodSecurityAdmission而不是PodSecurityPolicy的三个主要原因:将策略绑定到用户或服务帐户的模型削弱了安全性。功能不能平滑切换,没有安全策略不能关闭。API不一致且不灵活。新的PodSecurityAdmission机制在易用性和灵活性方面有了很大的提升。从使用的角度来看,有四个显着区别:可以在集群中默认开启,只要不加约束,就不会触发pod访问。确认。它只在命名空间级别生效,可以通过添加标签为不同的命名空间设置不同的安全限制。可以为特定用户、命名空间或运行时设置豁免规则。根据惯例,预先设置了三个安全级别,用户无需单独设置每个安全条件。工作方式PodSecurityAdmission将原有PodSecurityPolicy的安全条件分为三个预设的安全级别:privileged:Unrestricted,提供Pod的所有可用权限。基线:一种最低限度的限制策略,可防止已知的权限升级。restricted:严格限制策略,遵循当前pod加固的最佳实践。三个级别由松到严递增,分别包含不同的安全条件[3],适用于不同的pod工作场景。另外,安全级别可以设置为固定的Kubernetes版本,这样即使集群升级到新版本,新版本的安全级别定义发生变化,仍然可以根据集群的安全情况对Pod进行约束旧版。当一个pod与安全级别冲突时,我们可以通过三种模式选择不同的处理方式:enforce:只允许满足安全级别要求的pod,拒绝与安全级别冲突的pod。audit:只记录集群事件中的安全级别违规,不会拒绝pod。warn:当安全级别冲突时,会向用户返回警告信息,但不会拒绝pod。audit和warn模式是独立的,如果同时需要这两种功能,需要分别设置两种模式。应用安全策略不再需要创建单独的集群资源,只需要为命名空间设置控制标签:pod-security.kubernetes.io/:pod-security.kubernetes.io/-version:下面是一个更完整的例子。旧版本启用psa虽然PodSecurityAdmission是Kubernetesv1.22引入的功能,但旧版本可以通过安装PodSecurityadmissionwebhook来启用该功能。具体步骤如下:$gitclonehttps://github.com/kubernetes/pod-security-admission.git$cdpod-security-admission/webhook$makecerts$kubectlapply-k。以上来自官方文档的步骤在v1.18.17中会有两个兼容性问题。具体问题及解决方法如下:kubectl内置的kustomize版本不支持replacements字段:$kubectlapply-k。error:json:unknownfield"replacements"解决方法:安装最新版本的kusomize,执行$kustomizebuild。|kubectlapply-finthesamedirectory-manifest/50-deployment.yaml文件中定义的Deployment.spec.template.spec.containers[0].securityContext字段在v1.19才引入,所以v1.18需要修改该字段为对应注解版本,详见Seccomp[4]:error:errorvalidating"STDIN":errorvalidatingdata:ValidationError(Deployment.spec.template.spec.containers[0].securityContext):unknownfield"io.k8s.api中的“seccompProfile”。core.v1.SecurityContext;如果您选择忽略这些错误,请使用--validate=false关闭验证以验证psa安全限制首先创建一个新的命名空间psa-test对于测试,定义它以强制执行基线安全级别,并警告和审计限制级别:apiVersion:v1kind:Namespacemetadata:name:psa-testlabels:pod-security.kubernetes.io/enforce:baselinepod-security。kubernetes.io/enforce-version:v1.18#我们将这些设置为我们_desired_`enforce`级别。pod-security.kubernetes.io/audit:受限pod-security.kubernetes.io/audit-version:v1.18pod-security.kubernetes.io/warn:受限pod-security.kubernetes.io/warn-version:v1.18然后在此命名空间中创建上例中使用的部署:$kubectlcreate-fhostnetwork-pod.yaml-npsa-testdeployment.apps/nginx-hostnetworkcreated$kubectlgetdeploy-npsa-testnginx-hostnetworkNAMEREADY最新可用年龄Enginx-hostnetwork0/10017s$kubectl-npsa-testgetevent|grepPodSecurity104sWarningFailedCreatereplicaset/nginx-hostnetwork-644cdd6598Errorcreating:参考链接KEP-2579:PodSecurityAdmissionControl[5]PodSecur入场|Kubernetes[6]Pod安全标准|库伯内斯[7]