2022年2月我的CKS備考記錄


前言

CKA 和 CKS 是 LINUX 基金會聯合 CNCF社區組織的雲原生技術領域權威認證,考試采用實操方式進行。CKS全稱是Kubernetes安全專家認證,它在一個模擬真實的環境中測試考生對Kubernetes和雲安全的知識。在參加CKS考試之前,必須已經通過CKA(Kubernetes管理員認證),在獲得CKA認證之后才可以預約CKS考試。CKS 的考試難度相對於 CKA 提高了很多,2個小時的考試時間很緊張,因為考試是在外網上進行,這兩個考試又是實操考試,網絡條件不好,很影響效率,如果不抓緊的話,很可能做不完所有實操題。提醒備考的同學善用考試軟件提供的 notepad 功能,先把 yaml 文件或命令寫到notepad里,再粘貼到 terminal里。

我因為上次 CKA 考試還是比較順利,94 高分通過,所以這次的 CKS 考試有點疏忽了,搞忘帶身份證和護照,CKA/CKS 考試需要身份證+護照/信用卡,因此跟監考老師溝通了很久時間,最后修改了考試人姓名為中文,是用駕駛證完成的考試。意外之喜是 CKS 給我的證書是中文名的。

我這次考試的 kubernetes 版本是 1.22,特意記錄了一下考試會考到的知識點,分享給需要的同學。

1.NetworkPolicy

通常使用標簽選擇器來選擇pod,控制流量。所以要對 kubectl label的使用方法熟悉起來。

  kubectl label [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version] [options]

網絡策略的實用方法見注釋

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: test-network-policy
  namespace: default
spec:
  # podSelector: {} 表示選擇所有 pod 應用 NetworkPolicy
  podSelector: # 表示選擇包含標簽 role=db 的 pod 應用下面的 NetworkPolicy
    matchLabels:
      role: db
  policyTypes: # 表示 NetworkPolicy 包含 ingress 和 egress 流量規則
  - Ingress
  - Egress
  ingress: # ingress 規則白名單列表,每條規則允許同時匹配 from 和 ports  流,可以有條個規則。
  # 第1條白名單,包含 from + ports 的組合規則,允許來自172.17網段(172.17.1除外)、或標 簽 project=myproject 的命名空間的所 有 pod 、或 default 命名空間下標簽 role=frontend 的 pod 訪問(限 tcp 6379 端口)
  - from: 
    - ipBlock:
        cidr: 172.17.0.0/16
        except:
        - 172.17.1.0/24
    - namespaceSelector:
        matchLabels:
          project: myproject
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 6379
  # 第二條白名單,只包含 from 規則,允許來自所有命名空間包含 environment=testing 標簽的 pod 訪問(不限端口)
  - from:
    - namespaceSelector: {}
      podSelector:
        matchLabels:
          environment: testing
  egress: # egress 規則白名單列表,同 ingress 規則一樣,每條規則包含 to+ports,可以有多條規則。
  - to:
    - ipBlock:
        cidr: 10.0.0.0/24
    ports:
    - protocol: TCP
      port: 5978

2. Apparmor

查看當前節點加載的 apparmor profile ,如果沒有加載,要手工加載

apparmor_status|grep nginx

apparmor_parser /etc/apparmor.d/nginx_apparmor

cks 考試的 apparmor profile 文件內容:

#include <tunables/global>
#nginx-profile-3  
profile nginx-profile-3 flags=(attach_disconnected) {
  #include <abstractions/base>
  file,
  # Deny all file writes.
  deny /** w,
}

注意: nginx-profile-3 這一行要確保注釋掉,考試環境提供的可能沒有注釋,加載配置文件按時會報錯

root@node01:~# apparmor_parser  /etc/apparmor.d/nginx_apparmor
AppArmor parser error for /etc/apparmor.d/nginx_apparmor in /etc/apparmor.d/ninx_apparmor at line 2: Found unexpected character: '-'

修改 pod yaml 文件,在注釋里設置為 podx 加載 apparmor profile

annotations:
  container.apparmor.security.beta.kubernetes.io/podx: localhost/nginx-profile-3

yaml 文件內容如下:

apiVersion: v1
kind: Pod
metadata:
  name: podx
  annotations:
    container.apparmor.security.beta.kubernetes.io/podx: localhost/nginx-profile-3
spec:
  containers:
  - image: busybox
    imagePullPolicy: IfNotPresent
    name: podx
    command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
    resources: {}
  nodeName: node01
  dnsPolicy: ClusterFirst
  restartPolicy: Always

3. 修復kube-bench發現的安全問題

kube-bench 是一個 CIS 評估工具,掃描 kubernetes 集群存在的安全問題,基本上按照 掃描結果的修復建議進行修復就可以了,系統會給出很具體的修復措施。

# 修復 kube-apiserver 安全問題
vi /etc/kubernetes/manifests/kube-apiserver
#修改:
--authorization-mode=Node,RBAC
#添加
--insecure-port=0
#刪除
# --insecure-bind-address=0.0.0.0

#修復 kubelet 安全問題
vi /var/lib/kubelet/config.yaml
# 將authentication.anonymous.enabled 設置為 false
authentication:
  anonymous:
    enabled: false
# authorization.mode 設置為 Webhook
authorization:
  mode: Webhook
  
# 修復 etcd 安全問題
vi /etc/kubernetes/manifests/etcd.yaml
# 修改為true:
- --client-cert-auth=true

# 以上修復完成后 重新加載配置文件並重啟kubelet

systemctl daemon-reload
systemctl restart kubelet

4. 解決 pod 的 serviceaccount 設置錯誤問題

這個題要注意 serviceaccount 有個選項 automountServiceAccountToken, 這個選項決定是否自動掛載 secret 到 pod。
有這個選項,我們可以控制 pod 創建並綁定 serviceaccount 時,不自動掛載對應的 secret,這樣 pod 就沒有權限訪問 apiserver,提高了業務 pod 的安全性。

可以在 serviceaccount 和 pod 的 spec 里設置,pod的設置優先於 serviceaccount 里的設置。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: backend-sa 
  namespace: qa 
automountServiceAccountToken: false
apiVersion: v1
kind: Pod
metadata:
  name: backend
  namespace: qa
spec:
  serviceAccountName: backend-sa
  containers:
  - image: nginx:1.9
    imagePullPolicy: IfNotPresent
    name: backend

刪除未使用的 serviceaccount

5. 設置默認網絡策略

這道題是送分題,設置默認拒絕所有出站和入站的 pod 流量,基本上可以參考官網的案例直接改一下名字就可以了
默認網絡策略

6. RBAC

這道題也基本是送分題,參考官網文檔,根據題目要求,設置 role 的 資源訪問權限,綁定到 serviceaccount 就可以了。
RBAC

7. 日志審計

這道題稍復雜,需要按照要求啟動日志審計,包括兩個步驟:
(1) 編寫日志審計策略文件
日志審計策略

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
  - "RequestReceived"
rules:
  - level: RequestResponse   
    resources:
    - group: ""
      resources: ["namespaces"]
  
  - level: Request
    resources:
    - group: ""
      resources: ["persistentvolumes"] 
    namespaces: ["front-apps"]

  - level: Metadata
    resources:
    - group: ""
      resources: ["secrets", "configmaps"]

  - level: Metadata
    omitStages:
      - "RequestReceived"

(2) 修改 kube-apiserver.yaml配置文件,啟用日志審計策略,日志策略配置文件位置、日志文件存儲位置、循環周期。
啟動日志配置

vi /etc/kubernetes/manifests/kube-apiserver.yaml


# 設置日志審計策略文件在 pod 里的 mount 位置
- --audit-policy-file=/etc/kubernetes/logpolicy/sample-policy.yaml

# 設置日志文件存儲位置
- --audit-log-path=/var/log/kubernetes/audit-logs.txt

# 設置日志文件循環
- --audit-log-maxage=10    
- --audit-log-maxbackup=2

# mount 日志策略和日志文件的
volumeMounts:
  - mountPath: /etc/kubernetes/logpolicy/sample-policy.yaml
    name: audit
    readOnly: true
  - mountPath: /var/log/kubernetes/audit-logs.txt
    name: audit-log
    readOnly: false
volumes:
  - name: audit
    hostPath:
      path: /etc/kubernetes/logpolicy/sample-policy.yaml
      type: File
  - name: audit-log
    hostPath:
      path: /var/log/kubernetes/audit-logs.txt
      type: FileOrCreate

重啟 kubelet

systemctl daemon-reload
systemctl restart kubelet

8. 創建 secret

這道題考解碼 secret 的 base64 編碼信息,創建新的 secret 並 mount 到 pod 的特定位置。
解碼 secret

kubectl get secrets -n istio-system db1-test -o jsonpath={.data.username} | base64 -d >  /cks/sec/user.txt
kubectl get secrets -n istio-system db1-test -o jsonpath={.data.password} | base64 -d >  /cks/sec/pass.txt

創建secret

kubectl create secret generic db2-test -n istio-system --from-literal=username=production-instance --from-literal=password=KvLftKgs4aVH

使用secret

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
  namespace: istio-system
spec:
  containers:
  - name: dev-container
    image: nginx
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secret
  volumes:
  - name:
    secret:
      secretName: db2-test

9. 檢測 dockerfile 的不安全指令

這道題也是送分題,主要是把 dockerfile里兩個 使用了 root 用戶的指令刪除,把添加特定能力的 securityContext 安全上下文注釋掉。

# 刪除兩處
USER root

# 注釋 securityContext
# securityContext:
#   {"Capabilities": {'add':{NET_BIND_SERVICE}, 'drop: []'}, 'privileged': TRUE}

10. 運行沙箱容器

給出了 支持安全沙箱容器運行時 handler runsc, 我們需要創建一個 RuntimeClass 並在 pod spec里指定是用該 RuntimeClass
參考資料

  • 創建 RuntimeClass
apiVersion: node.k8s.io/v1beta1
kind: RuntimeClass
metadata:
  name: untrusted 
handler: runsc
  • 修改 server 命名空間 所有 pod,設置 runtimeClassName

注意:運行中的 pod 只能修改有限的幾個屬性,不支持修改 RuntimeClass,需要將所有 pod 的 yaml 解析出來,修改 yaml 后,再重新創建 pod

還需要修改deployment

    spec:。
      runtimeClassName: untrusted 
      containers:
      - image: vicuu/nginx:host
        imagePullPolicy: IfNotPresent
        name: nginx-host

11. 刪除 不符合最佳實踐的 pod

參考鏈接

  • 刪除啟用了特權的 pod
    主要是檢查 pod 是否含 privileged: true
    kubectl get po xxx -n production -o yaml| grep -i "privileged: true"

  • 刪除有狀態 pod
    kubectl get pods XXXX -n production -o jsonpath={.spec.volumes} | jq

12. 掃描鏡像安全漏洞並刪除使用有安全漏洞鏡像的pod

這道題考察對於鏡像掃描工具 trivy 的使用

# 獲取鏡像名
kubect get pod XXXX -n kamino -o yaml | grep image
# 掃描鏡像
trivy image -s HIGH,CRITICAL imagename
# kubectl delete po xxx

13. 使用 sysdig 檢查容器里里的異常進程

本體考察是否掌握 sysdig 的基本用法,記住兩個幫助命令:

  • sysdig -h 查看 sysdig 幫助
  • sysdig -l 查看 sysdig 支持的元數據

另外 sysdig 支持指定 containerid 分析特定容器

# 查看容器id
docker ps |grep tomcat
sysdig -M 30 -p "*%evt.time,%user.uid,%proc.name" container.id=xxxx>opt/DFA/incidents/summary

14. PodSecurityPolicy

這道題考察是否掌握 psp 的用法,包括5步驟
(1) 創建 psp
參考鏈接

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

(2) 創建 clusterrole,使用 psp

kubectl create clusterrole restrict-access-role --verb=use --resource=psp --resource-name=restrict-policy

(3) 創建 serviceaccount

kubectl create sa psp-denial-sa -n staging

(4) 綁定 clusterrole 到 serviceaccount

kubectl create clusterrolebinding dany-access-bind --clusterrole=restrict-access-role --serviceaccount=staging:psp-denial-sa

(5) 啟用 PodSecurityPolicy

vi /etc/kubernetes/manifests/kube-apiserver.yaml 
#確保有以下內容:
- --enable-admission-plugins=NodeRestriction,PodSecurityPolicy

15. 啟用 API server認證

這道題同前面 kube-bench 的考核內容有點重合,題目中是用 kubeamd創建的 kubernetes服務器權限設置有問題,允許未經授權的訪問。
參考鏈接
需要進行以下修改:

  • 使用 Node,RBAC 授權模式和 NodeRestriction 准入控制器
vi /etc/kubernetes/manifests/kube-apiserver.yaml
# 確保以下內容
- --authorization-mode=Node,RBAC
- --enable-admission-plugins=NodeRestriction
- --client-ca-file=/etc/kubernetes/pki/ca.crt
- --enable-bootstrap-token-auth=true
  • 刪除 system:anonymous 的 ClusterRolebinding角色綁定,取消匿名用戶的集群管理員權限
kubectl delete clusterrolebinding system:anonymous

16. ImagePolicyWebhook

這道題考察 ImagePolicyWebhook 准入控制器的使用,分4個步驟

  • 修改控制器配置文件,將未找到有效后端時的默認拒絕改為默認不拒絕
    參考鏈接

vi /etc/kubernetes/epconfig/admission_configuration.json

{

  "imagePolicy": {
     "kubeConfigFile": "/etc/kubernetes/epconfig/kubeconfig.yaml",
     "allowTTL": 50,
     "denyTTL": 50,
     "retryBackoff": 500,
     "defaultAllow": false
  }
}
  • 修改 控制器訪問 webhook server 的 kubeconfig
vi /etc/kubernetes/epconfig/kubeconfig.yaml

修改如下內容

apiVersion: v1
kind: Config
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/epconfig/webhook.pem
    server: https://acme.local:8082/image_policy  # web hook server 的地址
  name: bouncer_webhook
# 以下省略
  • 啟用ImagePolicyWebhook
    vi /etc/kubernetes/manifests/kube-apiserver.yaml
# 啟用 ImagePolicyWebhook
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
# 指定准入控制器配置文件
- --admission-control-config-file=/etc/kubernetes/epconfig/admission_configuration.json
# mount
    volumeMounts:
    - mountPath: /etc/kubernetes/epconfig
      name: epconfig
# 映射 volumes      
  volumes:
    - name: epconfig
    hostPath:
      path: /etc/kubernetes/epconfig
  • 測試是否生效
systemctl daemon-reload
systemctl restart kubelet
kubectl apply -f /cks/img/web1.yaml

有圖有真相

CKA

CKS


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM