← Back to Index

ocp scc

SecComp

https://docs.openshift.com/container-platform/4.3/authentication/managing-security-context-constraints.html

https://docs.docker.com/engine/security/seccomp/

https://docs.openshift.com/container-platform/4.3/nodes/nodes/nodes-nodes-managing.html

https://docs.openshift.com/container-platform/3.11/admin_guide/seccomp.html

https://gardener.cloud/050-tutorials/content/howto/secure-seccomp/

video

实验证明,容器内部更改date,不影响主机。


        # 在kube-system中创建特权用户
        
        oc project kube-system
        oc create serviceaccount -n kube-system demo-app
        oc adm policy add-scc-to-user privileged -z demo-app
        
        # 创建seccomp需要的security profile,我们这里创建一个只屏蔽clock set的profile
        
        cat << EOF > demo.yaml
        ---
        apiVersion: v1
        kind: ConfigMap
        metadata:
          name: seccomp-profile
          namespace: kube-system
        data:
          my-profile.json: |
            {
              "defaultAction": "SCMP_ACT_ALLOW",
              "syscalls": [
                {
                  "name": "clock_settime",
                  "action": "SCMP_ACT_ERRNO"
                }
              ]
            }
        EOF
        oc apply -f demo.yaml
        
        # 创建一个daemon set,把我们自定义的security profile复制到各个节点的containerd运行时配置目录中,这样containerd就可以根据需要,使用这个security profile
        
        cat << EOF > demo.yaml
        ---
        apiVersion: apps/v1
        kind: DaemonSet
        metadata:
          name: seccomp
          namespace: kube-system
          labels:
            security: seccomp
        spec:
          selector:
            matchLabels:
              security: seccomp
          template:
            metadata:
              labels:
                security: seccomp
            spec:
              initContainers:
              - name: installer
                image: docker.io/library/alpine:latest
                command: ["/bin/sh", "-c", "cp -r -L /seccomp/*.json /host/seccomp/"]
                securityContext:
                    privileged: true
                volumeMounts:
                - name: profiles
                  mountPath: /seccomp
                - name: hostseccomp
                  mountPath: /host/seccomp
                  readOnly: false
              containers:
              - name: pause
                image: gcr.io/google_containers/pause-amd64:3.0
              terminationGracePeriodSeconds: 5
              serviceAccount: demo-app
              volumes:
              - name: hostseccomp
                hostPath:
                  path: /var/lib/kubelet/seccomp
              - name: profiles
                configMap:
                  name: seccomp-profile
        EOF
        oc apply -f demo.yaml
        
        # 在我们的demo project中,创建特权用户
        
        oc project demo
        oc create serviceaccount -n demo demo-app
        oc adm policy add-scc-to-user privileged -z demo-app
        
        # 在demo project中,创建应用,指定使用我们刚创建的security profile,为了展现效果,我们特别的指明,需要clock setting这个权限,后面可以看到,security profile屏蔽了这个请求。
        
        cat << EOF > demo.yaml
        ---
        apiVersion: v1
        kind: Pod
        metadata:
          annotations:
            seccomp.security.alpha.kubernetes.io/pod: "localhost/my-profile.json"
          name: demo
        spec:
          nodeSelector:
            kubernetes.io/hostname: 'worker-0.ocp4.redhat.ren'
          restartPolicy: Always
          containers:
            - name: demo1
              image: >- 
                registry.redhat.ren:5443/docker.io/wangzheng422/centos:centos7-test
              env:
                - name: key
                  value: value
              command: ["/bin/bash", "-c", "--" ]
              args: [ "trap : TERM INT; sleep infinity & wait" ]
              imagePullPolicy: Always
              securityContext:
                capabilities:
                    add: ["CAP_SYS_TIME"]
          serviceAccount: demo-app
        EOF
        oc apply -n demo -f demo.yaml
        
        # 进入这个pod,运行命令能看到命令失败
        
        # this will failed, even you add the capabilities.
        
        date -s "1 second"
        
        # date: cannot set date: Operation not permitted
        
        # Tue Mar 24 02:10:49 UTC 2020
        
        # 为了对比,我们更改刚才的security profile,所有的都放开
        
        # try to allow
        
        cat << EOF > demo.yaml
        ---
        apiVersion: v1
        kind: ConfigMap
        metadata:
          name: seccomp-profile
          namespace: kube-system
        data:
          my-profile.json: |
            {
              "defaultAction": "SCMP_ACT_ALLOW"
            }
        EOF
        oc apply -f demo.yaml
        
        # 通过打标签的方法,让daemon set重启,这样就把我们更新的security profile更新到各个节点上去
        
        # restart damonset and restart pod.
        
        # oc annotate -n kube-system ds seccomp last-update="`date`"
        
        oc patch -n kube-system ds seccomp -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"
        oc get pod -n kube-system
        
        # 进入demo pod,再次运行命令,可以看到命令运行成功。 
        
        # this command will ok.
        
        date -s "1 second"
        
        # 最好,为了防止安全风险,我们将security profile重置成拒绝所有,并重启daemon set,更新到所有节点上。
        
        # finally, restore 
        
        cat << EOF > demo.yaml
        ---
        apiVersion: v1
        kind: ConfigMap
        metadata:
          name: seccomp-profile
          namespace: kube-system
        data:
          my-profile.json: |
            {
              "defaultAction": "SCMP_ACT_ERRNO"
            }
        EOF
        oc apply -f demo.yaml
        
        # restart damonset and restart pod.
        
        oc patch -n kube-system ds seccomp -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"`date +'%s'`\"}}}}}"

capabilities

video


        # 创建pod,限制selinux,没有clock setting的capability.
        
        cat << EOF > demo.yaml
        ---
        kind: Deployment
        apiVersion: apps/v1
        metadata:
          annotations:
          name: demo
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: demo
          template:
            metadata:
              labels:
                app: demo  
            spec:
              nodeSelector:
                kubernetes.io/hostname: 'infra1.hsc.redhat.ren'
              restartPolicy: Always
              containers:
                - name: demo1
                  image: >- 
                    registry.redhat.ren:5443/docker.io/wangzheng422/centos:centos7-test
                  env:
                    - name: key
                      value: value
                  command: ["/bin/bash", "-c", "--" ]
                  args: [ "trap : TERM INT; sleep infinity & wait" ]
                  imagePullPolicy: Always
                  securityContext:
                    capabilities:
                        drop: ["CAP_SYS_TIME"]
              serviceAccount: demo-app
        
        EOF
        oc apply -n demo -f demo.yaml
        
        # 进入pod,运行以下命令,不成功
        
        date -s "1 second"
        
        # 更新这个pod,赋予clock setting的capability
        
        cat << EOF > demo.yaml
        ---
        kind: Deployment
        apiVersion: apps/v1
        metadata:
          annotations:
          name: demo
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: demo
          template:
            metadata:
              labels:
                app: demo  
            spec:
              nodeSelector:
                kubernetes.io/hostname: 'infra1.hsc.redhat.ren'
              restartPolicy: Always
              containers:
                - name: demo1
                  image: >- 
                    registry.redhat.ren:5443/docker.io/wangzheng422/centos:centos7-test
                  env:
                    - name: key
                      value: value
                  command: ["/bin/bash", "-c", "--" ]
                  args: [ "trap : TERM INT; sleep infinity & wait" ]
                  imagePullPolicy: Always
                  securityContext:
                    capabilities:
                        add: ["CAP_SYS_TIME"]
              serviceAccount: demo-app
        
        EOF
        oc apply -n demo -f demo.yaml
        
        # 进入pod,运行命令,可以看到命令运行成功
        
        date -s "1 second"
        
        # 删除演示应用
        
        oc delete -n demo -f demo.yaml
        

MCS

https://access.redhat.com/documentation/en-us/openshift_container_platform/3.3/html/installation_and_configuration/configuring-persistent-storage#selinuxoptions

http://www.178linux.com/98614

https://access.redhat.com/sites/default/files/video/files/mls_-_wide_8.pdf

https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/mls

https://www.cnblogs.com/charlieroro/p/10830721.html

video


        # on worker-0
        
        # yum install selinux-policy-mls
        
        # vi /etc/selinux/config
        
        # # SELINUXTYPE=mls
        
        # # SELINUXTYPE=mls
        
        # getenforce
        
        # fixfiles -F onboot
        
        # cat /.autorelabel | less
        
        # semanage login -l
        
        # # semanage login --modify --range s0-s15:c0.c1023 root
        
        # chcon -R -t default_t /data/mcs
        
        # 创建测试用的目录,设置特殊的权限。
        
        mkdir /data/mcs
        chcon -R -l s0:c100 /data/mcs
        chcon -R -t container_file_t /data/mcs
        chown -R 1000:2000 /data/mcs
        chmod -R 775 /data/mcs
        
        # semanage fcontext -l | grep default_t
        
        oc get project demo -o yaml 
        
        # metadata:
        
        #   annotations:
        
        #     openshift.io/description: ""
        
        #     openshift.io/display-name: ""
        
        #     openshift.io/requester: kube:admin
        
        #     openshift.io/sa.scc.mcs: s0:c23,c22
        
        #     openshift.io/sa.scc.supplemental-groups: 1000550000/10000
        
        #     openshift.io/sa.scc.uid-range: 1000550000/10000
        
        # 创建pod,指定selinux的权限s0:c99。
        
        cat << EOF > demo.yaml
        ---
        apiVersion: v1
        kind: Pod
        metadata:
          annotations:
          name: demo
        spec:
          nodeSelector:
            kubernetes.io/hostname: 'infra1.hsc.redhat.ren'
          restartPolicy: Always
          containers:
            - name: demo1
              image: >- 
                registry.redhat.ren:5443/docker.io/wangzheng422/centos:centos7-test
              env:
                - name: key
                  value: value
              command: ["/bin/bash", "-c", "--" ]
              args: [ "trap : TERM INT; sleep infinity & wait" ]
              imagePullPolicy: Always
              securityContext:
                runAsUser: 1000
                runAsGroup: 2000 
                seLinuxOptions:
                  level: 's0:c99'
              volumeMounts:
                - mountPath: /data
                  name: demo 
                  readOnly: false
          serviceAccount: demo-app
          volumes:
            - name: demo 
              hostPath:
                path: /data/mcs
                type: Directory
        EOF
        oc apply -n demo -f demo.yaml
        
        # 进入pod检查权限,由于s0:c99 和目录的s0:c100 权限不符,以下操作失败
        
        # below will fail
        
        cd /data
        
        # 修改目录权限,符合pod中的selinux声明
        
        # after change the host path selinux flag
        
        chcon -R -l s0:c99 /data/mcs
        
        # system_u:object_r:default_t:s0:c99
        
        # system_u:system_r:container_t:s0:c99
        
        # seinfo -tcontainer_t
        
        # seinfo -rsystem_r
        
        # 进入pod操作,以下操作能够成功。
        
        # then, below will ok
        
        cd /data
        ls
        touch test