跳转至

05供应链安全

考试大纲

供应链安全:20%

  • 最小化基本镜像大小
  • 保护您的供应链:将允许的注册表列入白名单,对镜像进行签名和验证
  • 使用用户工作负载的静态分析(例如 kubernetes 资源,Docker 文件)
  • 扫描镜像,找出已知的漏洞

ImagePolicyWebhook 容器镜像扫描

题目描述:

  • luster 上设置了容器镜像扫描器,但尚未完全集成到 cluster 的配置中。

完成后,容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用。

注意:你必须在 cluster 的 master 节点上完成整个考题,所有服务和文件都已被准备好并放置在该节点上。

给定一个目录 /etc/kubernetes/epconfig 中不完整的配置,

以及具有 HTTPS 端点 https://image-bouncer-webhook.default.svc:1323/image_policy 的功能性容器镜像扫描器:

  1. 启用必要的插件来创建镜像策略

  2. 校验控制配置并将其更改为隐式拒绝(implicit deny)

  3. 编辑配置以正确指向提供的 HTTPS 端点

最后,通过尝试部署易受攻击的资源 /cks/img/web1.yaml 来测试配置是否有效。

参考解答:

编辑 admission_configuration.json(题目会给这个目录),修改 defaultAllow 为 false

# /etc/kubernetes/epconfig/admission_configuration.json
……
 "denyTTL": 50,
 "retryBackoff": 500,
 "defaultAllow": false #将 true 改为 false
……

编辑 /etc/kubernetes/epconfig/kubeconfig.yml,添加 webhook server 地址

# vi /etc/kubernetes/epconfig/kubeconfig.yml
certificate-authority: /etc/kubernetes/epconfig/server.crt
server: https://image-bouncer-webhook.default.svc:1323/image_policy #添加 webhook server 地址
name: bouncer_webhook

编辑 kube-apiserver.yaml,从官网中引用 ImagePolicyWebhook 的配置信息

# /etc/kubernetes/manifests/kube-apiserver.yaml
# 在- command:下修改或添加如下内容,注意空格要对齐
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook #注意先搜索,如果存在则修改,比如模拟环境里已经有了,但不全,需要修改。
- --admission-control-config-file=/etc/kubernetes/epconfig/admission_configuration.json #在 1.27 的考试中,默认有这行了,但为了以防万一,模拟环境,没有这行,需要你手动添加。考试时,你先检查,有的话,就不要再重复添加了。

等待apiserver自动重启,并恢复

创建易受攻击的资源 /cks/img/web1.yaml 来测试配置是否有效。因为模拟环境里的 image_policy 策略是镜像 tag 是 latest 的不允许创建,则验证成功。

注意:考试时,你可能会正常的创建出来 pod。但是题目里会给你一个日志文件,你可以检查日志文件,日志文件里会记录检测信息的,如果有提示大概意思是说部署了一个易受攻击的镜像,则表示做对了。

Dockerfile 检测

题目描述:

  • 分析和编辑给定的 Dockerfile /cks/docker/Dockerfile(基于 ubuntu:16.04 镜像),并修复在文件中拥有的突出的安全/最佳实践问题的两个指令

分析和编辑给定的清单文件 /cks/docker/deployment.yaml ,并修复在文件中拥有突出的安全/最佳实践问题的两个字段

注意:

1、请勿添加或删除配置设置;只需修改现有的配置设置让以上两个配置设置都不再有安全/最佳实践问题

2、如果您需要非特权用户来执行任何项目,请使用用户 ID 65535 的用户 nobody

只修改即可,不需要创建。

文件

# /cks/docker/Dockerfile
FROM ubuntu:last
RUN apt-get install -y wget curl gcc gcc-c++ make openssl-devel pcre-devel gd-devel \
          iproute net-tools telnet && \
         yum clean all && \
         rm -rf /var/cache/apt/*
USER root
COPY sunnydale.sh .
ADD nginx-1.15.5.tar.gz /
RUN cd nginx-1.15.5 && \
    ./configure --prefix=/usr/local/nginx \
    --with-http_ssl_module \
    --with-http_stub_status_module && \
    make -j 4 && make install && \
    mkdir /usr/local/nginx/conf/vhost && \
    cd / && rm -rf nginx* && \
   ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
USER root
CMD ["./sunnydale.sh"]
ENV PATH $PATH:/usr/local/nginx/sbin
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["nginx","-g","daemon off;"]

文件

# /cks/docker/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: couchdb
  namespace: default
  labels:
    app: couchdb
    version: stable
spec:
  replicas: 1
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: couchdb
      version: stable
  template:
    metadata:
      labels:
        app: couchdb
        version: stable
    spec:
      containers:
      - name: couchdb 
        image: demo:v1
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /healthCheck
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
          periodSeconds: 30
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /healthCheck
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
          periodSeconds: 10
          successThreshold: 1
          failureThreshold: 5
        ports:
          - name: http
            containerPort: 8080
            protocol: TCP
        volumeMounts:
          - name: database-storage
            mountPath: /var/lib/database
        securityContext:
          {'capabilities': {'add': ['NET_BIND_SERVICE'], 'drop': ['all']}, 'privileged': True, 'readOnlyRootFilesystem': False, 'runAsUser': 65535}
        resources:
          limits:
            cpu: 300m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 100Mi
      volumes:
        - name: database-storage
          emptyDir: {}

参考解答:

修改 /cks/docker/Dockerfile 文件问题

FROM ubuntu:16.04 # 镜像版本修改为16.04
RUN apt-get install -y wget curl gcc gcc-c++ make openssl-devel pcre-devel gd-devel \
          iproute net-tools telnet && \
         yum clean all && \
         rm -rf /var/cache/apt/*
USER nobody # 用户修改为 nobody
COPY sunnydale.sh .
ADD nginx-1.15.5.tar.gz /
RUN cd nginx-1.15.5 && \
    ./configure --prefix=/usr/local/nginx \
    --with-http_ssl_module \
    --with-http_stub_status_module && \
    make -j 4 && make install && \
    mkdir /usr/local/nginx/conf/vhost && \
    cd / && rm -rf nginx* && \
   ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
USER nobody # 用户修改为 nobody
CMD ["./sunnydale.sh"]
ENV PATH $PATH:/usr/local/nginx/sbin
COPY nginx.conf /usr/local/nginx/conf/nginx.conf
WORKDIR /usr/local/nginx
EXPOSE 80
CMD ["nginx","-g","daemon off;"]

修改 /cks/docker/deployment.yaml 文件问题

apiVersion: apps/v1
kind: Deployment
metadata:
  name: couchdb
  namespace: default
  labels:
    app: couchdb
    version: stable
spec:
  replicas: 1
  revisionHistoryLimit: 3
  selector:
    matchLabels:
      app: couchdb
      version: stable
  template:
    metadata:
      labels:
        app: couchdb
        version: stable
    spec:
      containers:
      - name: couchdb 
        image: demo:v1
        imagePullPolicy: IfNotPresent
        livenessProbe:
          httpGet:
            path: /healthCheck
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
          periodSeconds: 30
          successThreshold: 1
          failureThreshold: 5
        readinessProbe:
          httpGet:
            path: /healthCheck
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 30
          timeoutSeconds: 5
          periodSeconds: 10
          successThreshold: 1
          failureThreshold: 5
        ports:
          - name: http
            containerPort: 8080
            protocol: TCP
        volumeMounts:
          - name: database-storage
            mountPath: /var/lib/database
        securityContext:
          {'capabilities': {'add': ['NET_BIND_SERVICE'], 'drop': ['all']}, 'privileged': False, 'readOnlyRootFilesystem': True, 'runAsUser': 65535} # 修改 privileged 为 False,readOnlyRootFilesystem 为 True
        resources:
          limits:
            cpu: 300m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 100Mi
      volumes:
        - name: database-storage
          emptyDir: {}

Trivy 扫描镜像安全

题目描述:

  • 使用 Trivy 开源容器扫描器检测 namespace kamino 中 Pod 使用的具有严重漏洞的镜像。

查找具有 HighCritical 严重性漏洞的镜像,并删除使用这些镜像的 Pod。

注意:Trivy 仅安装在 cluster 的 master 节点上,

在工作节点上不可使用。

你必须切换到 cluster 的 master 节点才能使用 Trivy。

参考解答:

查找 namespace kamino 中所有 Pod 的镜像

candidate@master01:~$ kubectl describe pod -n kamino |grep -iE '^Name:|Image:'
Name:             tri111
    Image:         amazonlinux:1
Name:             tri222
    Image:         amazonlinux:2
    Image:          nginx:1.19
Name:             tri333
    Image:          vicuu/nginx:host
    Image:         amazonlinux:2
Name:             tri444
    Image:         amazonlinux:2

检查镜像是否有高危和严重的漏洞

trivy image -s HIGH,CRITICAL amazonlinux:1
trivy image -s HIGH,CRITICAL amazonlinux:2
trivy image -s HIGH,CRITICAL nginx:1.19
trivy image -s HIGH,CRITICAL vicuu/nginx:host

找到具有HighCritical的 Pod 进行删除

kubectl delete pod -n kamino <pod的名字>