zoukankan      html  css  js  c++  java
  • Kubernetes 中的 Pod 安全策略

    来源:伪架构师

    作者:崔秀龙

    很多人分不清 SecurityContext 和 PodSecurityPolicy 这两个关键字的差别,其实很简单:

    •SecurityContext 是 Pod 中的一个字段,而 PSP 是一个独立的资源类型。

    •SecurityContext 是 Pod 自身对安全上下文的声明;

    而 PSP 则是强制实施的——不合规矩的 Pod 无法创建。

    PSP 的用法和 RBAC 是紧密相关的,换句话说,应用 PSP 的基础要求是:

    •不同运维人员的操作账号需要互相隔离并进行单独授权。

    •不同命名空间,不同 ServiceAccount 也同样要纳入管理流程。

    PSP 环境下,运维人员或者新应用要接入集群,除了 RBAC 设置之外,还需要声明其工作范围所需的安全策略,并进行绑定,才能完成工作。

    PSP 的官方文档中提到,PSP 是通过 Admission Controller 启用的,并且注明了:启用 PSP 是一个有风险的工作,未经合理授权,可能导致 Pod 无法创建。

    开始之前,首先设置一个别名,在 default 命名空间新建 ServiceAccount 来模拟一个有权创建 Pod 的用户:

    $ kubectl create sa common
    serviceaccount/common created
    
    $ kubectl create rolebinding common --clusterrole=edit --serviceaccount=default:common
    rolebinding.rbac.authorization.k8s.io/common created
    
    $ alias kube-common='kubectl --as=system:serviceaccount:default:common'
    



    第一个 PSP

    我们首先创建一个不允许创建特权 Pod 的策略:

    apiVersion: policy/v1beta1
    kind: PodSecurityPolicy
    metadata:
    name: noprivileged
    spec:
    privileged: false
    seLinux:
    rule: RunAsAny
    supplementalGroups:
    rule: RunAsAny
    runAsUser:
    rule: RunAsAny
    fsGroup:
    rule: RunAsAny
    volumes:
    - '*'
    



    保存为 psp.noprivileged.yaml 并提交给集群。

    接下来创建两个 Pod:

    apiVersion: v1
    kind: Pod
    metadata:
    name: noprivileged
    spec:
    containers:
    - name: pause

    image: k8s.gcr.io/pause

    apiVersion: v1
    kind: Pod
    metadata:
    name: privileged
    spec:
    containers:
    - name: pause
    image: k8s.gcr.io/pause
    securityContext:
      privileged: true
    



    用普通用户创建这个 Pod:

    $ kube-common apply -f pod.yaml && kube-common delete -f pod.yaml
    pod/noprivileged created
    pod/privileged created
    pod "noprivileged" deleted
    pod "privileged" deleted
    



    可以看到,在不允许创建特权容器的规则之中,我们的用户还是能够创建特权容器,这是因为还没启用 PSP,接下来在集群设置中启动 PSP,各种环境的启用方式不同,例如在 GKE 环境:

    $ gcloud beta container clusters update gcp-k8s --enable-pod-security-policy --zone=asia-east1-a
    Updating gcp-vlab-k8s...done.
    



    删除重建 Pod:

    $ kube-common apply -f pod.yaml && kube-common delete -f pod.yaml
    Error from server (Forbidden): error when creating "pod.yaml": pods "noprivileged" is forbidden: unable to validate against any pod security policy: []
    Error from server (Forbidden): error when creating "pod.yaml": pods "privileged" is forbidden: unable to validate against any pod security policy: []
    



    可以看到,Pod 的新建请求被拒绝了——然而使用集群管理员身份还是能成功创建的:

    $ kubectl apply -f pod.yaml && kubectl delete -f pod.yaml
    pod/noprivileged created
    pod/privileged created
    pod "noprivileged" deleted
    pod "privileged" deleted
    



    全员 admin 是万恶之源。

    用 RBAC 进行授权:

    $ kubectl create role psp:noprivileged 
    --verb=use 
    --resource=podsecuritypolicy 
    --resource-name=noprivileged
    role.rbac.authorization.k8s.io/psp:noprivileged created
    
    $ kubectl create rolebinding common:psp:noprivileged 
    --role=psp:noprivileged 
    --serviceaccount=default:common
    rolebinding.rbac.authorization.k8s.io/common:psp:noprivileged created
    



    再试试普通用户的能力:

    $ kube-common apply -f pod.yaml ; kube-common delete -f pod.yaml
    pod/noprivileged created
    Error from server (Forbidden): error when creating "pod.yaml": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
    pod "noprivileged" deleted
    Error from server (NotFound): error when deleting "pod.yaml": pods "privileged" not found
    



    非特权 Pod 才能够成功创建,这符合我们的预期。

    副作用

    Pod 成功创建了之后,顺理成章,做个 Deployment 看看:

    kind: Deployment
    metadata:
    name: privileged
    spec:
    replicas: 1
    template:
    metadata:
      labels:
        app: pause
        version: v1
    spec:
      containers:
      - name: sleep
        image: k8s.gcr.io/pause
        securityContext:

    privileged: true

    apiVersion: extensions/v1beta1
    kind: Deployment
    metadata:
    name: noprivileged
    spec:
    replicas: 1
    template:
    serviceAccount: common
    metadata:
      labels:
        app: pause
        version: v1
    spec:
      containers:
      - name: sleep
        image: k8s.gcr.io/pause
    



    我们会发现,Deployment 无法正常工作:

    $ kubectl get pods
    kuNo resources found in default namespace.
    $ kubectl get deployment
    NAME           READY   UP-TO-DATE   AVAILABLE   AGE
    noprivileged   0/1     0            0           15m
    privileged     0/1     0            0           15m
    



    查看一下事件:

    $ kubectl get events | grep policy
    8m38s       Warning   FailedCreate        replicaset/noprivileged-6f94f9c9b8                 Error creating: pods "noprivileged-6f94f9c9b8-" is forbidden: unable to validate against any pod security policy: []
    8m38s       Warning   FailedCreate        replicaset/privileged-6d78d5458                    Error creating: pods "privileged-6d78d5458-" is forbidden: unable to validate against any pod security policy: []
    



    这次的 Pod 不是由我们授权的 common 用户创建的,而是由 RS Controller 启动的,因此会失败,加入一个 Service Account:

    ...
    spec:
      serviceAccount: common
      containers:
    ...
    spec:
      serviceAccount: common
      containers:
    ...
    



    提交变更,会发现非特权 Pod 开始创建:

    $ kubectl get pods
    NAME                            READY   STATUS    RESTARTS   AGE
    noprivileged-6cf595c5bd-rc8cx   1/1     Running   0          4s
    



    系统 Pod 怎么办

    这时候我想到个问题,其它 Pod 会不会受到影响?我删除了 kube-system 下面的一个 kube-proxy的 Pod,发现这个 Pod 自动重建了,没有受到 PSP 的影响,查看一下 RBAC 相关配置,会发现 GCP 在更新集群的过程中已经为系统服务进行了预设:

    $ kubectl get rolebinding
    ...
    gce:podsecuritypolicy:kube-proxy                    80m
    gce:podsecuritypolicy:metadata-agent                80m
    gce:podsecuritypolicy:metadata-proxy                80m
    gce:podsecuritypolicy:nodes                         80m
    ...
    



    追查下去:

    $ kubectl get rolebinding gce:podsecuritypolicy:metadata-proxy -o yaml
    ...
    roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: gce:podsecuritypolicy:privileged
    subjects:
    - kind: ServiceAccount
    name: metadata-proxy
    namespace: kube-system
    



    如果追查其中涉及到的 ClusterRole,会发现它指向一个 PSP:

    $ kubectl get clusterrole gce:podsecuritypolicy:privileged -o yaml
    ...
    rules:
    - apiGroups:
    - policy
    resourceNames:
    - gce.privileged
    resources:
    - podsecuritypolicies
    verbs:
    - use
    



    看看这个 PSP 的内容:

    $ kubectl get psp  gce.privileged -o yaml
    ...
    privileged: true
    ...
    



    的确包含了特权 Pod 的内容。

    最后看看负责创建这个特权 Pod 的 Daemonset:

    $  kubectl get daemonset  metadata-proxy-v0.1 -o yaml
    ...
      serviceAccount: metadata-proxy
      serviceAccountName: metadata-proxy
    ...
    



    PSP的限制能力

    分为以下几个大方面:

    •特权容器

    •主机命名空间:

    例如 HostPID、HostNetwork 等。

    •卷和文件系统:

    例如 PVC、configMap、emptyDir 等卷类型,以及 fsGroup、AllowedHostPaths 等加载能力。

    •用户和组:

    运行身份

    •提权:

    是否允许

    •Capability 和 sysctl

    •SeLinux、AppArmor 等。

    马后炮

    kubectl 的 advise-psp 插件,能够根据当前运行的 Pod,提取出所需的 PSP 信息。

    参考链接:

    https://kubernetes.io/docs/con ... licy/

  • 相关阅读:
    select中添加、修改、删除option元素
    asp之ajax技术:responstext中文乱码
    JAVA中的AJAX技术
    asp之IIS服务器:Windows2003 IIS6服务器上传文件不能超过200k解决方案
    ghost系统安装盘与普通安装盘有何区别?
    简单破解忘记Windows密码的解决方法
    删除用户账户密码
    asp数据库 rs.open语句详解
    asp函数 生成随机数
    microsoft Report view项目部署出错
  • 原文地址:https://www.cnblogs.com/alauda/p/12867743.html
Copyright © 2011-2022 走看看