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

  • https://www.bilibili.com/video/BV1Sa4y1x7UP/
  • https://youtu.be/gwu53N4dIws

实验证明,容器内部更改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

  • https://youtu.be/yLdJghw-7xs
  • https://www.bilibili.com/video/BV1x64y1T7BZ/
# 创建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

  • https://youtu.be/XoQ11ZXEL7Y
  • https://www.bilibili.com/video/BV115411t777/
# 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