Featured image of post Kubernetes考试题(CKS)

Kubernetes考试题(CKS)

CKS 指的是 Certified Kubernetes Security Specialist,是 Kubernetes 安全认证考试,由云原生计算基金会 (CNCF) 管理和推出。CKS 考试旨在评估个人在 Kubernetes 安全方面的知识和技能,包括设计和构建安全的容器化应用程序、保护 Kubernetes 平台和主机安全、防范网络攻击和数据泄露等方面。。。。。。。。

CKS认证

CKS 指的是 Certified Kubernetes Security Specialist,是 Kubernetes 安全认证考试,由云原生计算基金会 (CNCF) 管理和推出。CKS 考试旨在评估个人在 Kubernetes 安全方面的知识和技能,包括设计和构建安全的容器化应用程序、保护 Kubernetes 平台和主机安全、防范网络攻击和数据泄露等方面。

通过 CKS 认证可以证明您具备 Kubernetes 安全方面的专业知识和技能,并为企业提供 Kubernetes 安全方面的专家和顾问。CKS 认证需要先取得 CKA (Certified Kubernetes Administrator) 认证,在此基础上进一步考核 Kubernetes 安全方面的能力。

为了准备 CKS 考试,您可以参加官方组织的培训课程,也可以通过自学来获得相关知识。考试内容涵盖 Kubernetes 安全的各个方面,例如身份验证和授权、网络安全、加密、漏洞管理等等。

CKS题库

CKS考试概要:

考试模式:线上考试 考试时间:2小时 题目数量:16题 分数:总100分,66分及格 题目变化:每次考题会对里面涉及的命名空间、资源名称个别微调,还有题目顺序。

1、kube-bench 修复不安全项

https://kubernetes.io/zh/docs/reference/config-api/kubelet-config.v1beta1/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Context 针对 kubeadm 创建的 cluster 运行 CIS 基准测试工具时, 发现了多个必须立即解决的问题。 Task
通过配置修复所有问题并重新启动受影响的组件以确保新的设置生效。 修复针对 API 服务器发现的所有以下违规行为: 1.2.7 Ensure
that the --authorization-mode argument is not set to AlwaysAllow 1.2.8
Ensure that the --authorization-mode argument includes Node 1.2.9
Ensure that the --authorization-mode argument includes RBAC 1.2.18
Ensure that the --insecure-bind-address argument is not set 1.2.19
Ensure that the --insecure-port argument is set to 0 FAIL FAIL FAIL
FAIL FAIL 修复针对 kubelet 发现的所有以下违规行为: Fix all of the following
violations that were found against the kubelet: 4.2.1 Ensure that the
anonymous-auth argument is set to false 4.2.2 Ensure that the
–authorization-mode argument is not set to AlwaysAllow FAIL FAIL 注意:尽可能使用 Webhook 身份验证/授权。 修复针对 etcd 发现的所有以下违规行为: Fix all of the
following violations that were found against etcd: 2.2 Ensure that the
–client-cert-auth argument is set to true FAIL

解读:使用kube-bench工具检查集群组件配置文件存在的问题与修复,并重启对应组件确保新配置生效。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#切换环境
kubectl config use-context KSCS00201 
#
ssh master01 
sudo -i 

修改api-server 
kube-bench master 
mkdir bak1 

cp /etc/kubernetes/manifests/kube-apiserver.yaml    bak1/ 
vim /etc/kubernetes/manifests/kube-apiserver.yaml 
#修改、添加、删除相关内容 
#修改authorization-mode,注意Node和RBAC之间的符号是英文状态的逗号,而不是点。 
    - --authorization-mode=Node,RBAC 
#删除insecure-bind-address,考试中,有可能本来就没写这行。 
    - --insecure-bind-address=0.0.0.0 


修改kubelet
#可以使用这条命令查,要记住 
kube-bench node 
 
修改  /var/lib/kubelet/config.yaml 
apiVersion: kubelet.config.k8s.io/v1beta1 
authentication: 
  anonymous:          #修改anonymous下的,将true改为false 
    enabled: false       #改为false 
  webhook: 
    cacheTTL: 0s 
    enabled: true 
  x509: 
    clientCAFile: /etc/kubernetes/pki/ca.crt 
authorization:           #修改authorization下的 
  mode: Webhook   #改为Webhook 
  webhook: 
…… 


修改etcd 
#可以使用这条命令查,要记住 
kube-bench 

修改之前,备份一下配置文件。 
mkdir bak1 
cp /etc/kubernetes/manifests/etcd.yaml    bak1/ 
vim /etc/kubernetes/manifests/etcd.yaml 
修改 
    - --client-cert-auth=true     #修改为true 
1
2
3
4
5
6
7
修改完成后,等待2分钟,再检查一下所有pod,确保模拟环境里的所有pod都正常。 
kubectl get pod -A 
 
# 退出root,退回到candidate@master01 
exit 
# 退出master01,退回到candidate@node01 
exit 

2、Pod指定ServiceAccount

1
2
3
4
5
Task 
1. 在现有 namespace qa 中创建一个名为 backend-sa 的新 ServiceAccount, 确保此
ServiceAccount 不自动挂载 API 凭据。 
2. 使用 /cks/sa/pod1.yaml 中的清单文件来创建一个 Pod。
3. 最后,清理 namespace qa 中任何未使用的 ServiceAccount。

https://kubernetes.io/zh/docs/tasks/configure-pod-container/configure-service-account/#%E4%BD%BF%E7%94%A8%E9%BB%98%E8%AE%A4%E7%9A%84%E6%9C%8D%E5%8A%A1%E8%B4%A6%E6%88%B7%E8%AE%BF%E9%97%AE-api-%E6%9C%8D%E5%8A%A1%E5%99%A8

1680578239537

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# kubectl config use-context KSCH0030

1  创建ServiceAccount 
vi qa-ns.yaml 
根据官网修改如下内容 
apiVersion: v1 
kind: ServiceAccount 
metadata: 
  name: backend-sa     #修改name 
  namespace: qa         #注意添加namespace 
automountServiceAccountToken: false   #修改为false,表示不自动挂载  secret 
 
kubectl apply -f qa-ns.yaml 
kubectl get sa -n qa 



2 创建Pod使用该ServiceAccount 
vi /cks/sa/pod1.yaml 

修改如下内容 
 
…… 
metadata: 
  name: backend 
  namespace: qa     #注意命名空间是否对 
spec: 
  serviceAccountName: backend-sa    #  没有则添加一行,有则修改这一行为刚才创建ServiceAccount(考试时,默认已有这一行,需要修改。) 
  containers: 
…… 
 
kubectl apply -f /cks/sa/pod1.yaml 
kubectl get pod -n qa 



3. 删除没有使用的ServiceAccount 
 
查看所有sa 
kubectl get sa -n qa 
 
查看已经在用的sa 
kubectl get pod -n qa -o yaml | grep -i serviceAccountName 
 
删除不用的sa 
kubectl delete sa test01 -n qa 
 

3、默认网络策略

1
2
3
4
5
6
7
8
Context 
一个默认拒绝(default-deny)的NetworkPolicy可避免在未定义任何其他NetworkPolicy的namespace中意外公开Pod。 
 Task 
为所有类型为Ingress+Egress 的流量在namespace testing中创建一个名为denypolicy的新默认拒绝NetworkPolicy。 
此新的NetworkPolicy必须拒绝namespace testing中的所有的Ingress + Egress 流量。 
将新创建的默认拒绝NetworkPolicy应用与在namespace testing中运行的所有Pod。 
 
你可以在  /cks/net/p1.yaml找到一个模板清单文件。

https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/#%E9%BB%98%E8%AE%A4%E6%8B%92%E7%BB%9D%E6%89%80%E6%9C%89%E5%85%A5%E5%8F%A3%E5%92%8C%E6%89%80%E6%9C%89%E5%87%BA%E7%AB%99%E6%B5%81%E9%87%8F

解读:在testing命名空间创建一个名为denypolicy的网络策略。拒绝所有Ingress和 Egress流量。将网络策略应用到testing命名空间中的所有pod。

1680578883654

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# kubectl config use-context KSCS00101 

创建名为  denypolicy的  NetworkPolicy,拒绝testing命名空间内所有Ingress + Egress 流量 
(这里可能是ingress 或egress或ingress+egress,根据题目要求写。) 
vi /cks/net/p1.yaml 

…… 
metadata: 
  name: denypolicy    #修改name 
  namespace: testing    #注意添加namespace 
spec: 
  podSelector: {} 
  policyTypes: 
  - Ingress       #注意看题,是Ingress + Egress(入口+出口),还是只是Ingress 或只是Egress。 
  - Egress       #在1.23的考试中,只要求拒绝所有Egress流量,那就只写这这个- Egress即可,这种情况就不要写- Ingress 了。 
 
创建 
kubectl apply -f /cks/net/p1.yaml 
 
检查 
kubectl describe networkpolicy denypolicy -n testing 

4、RBAC - RoleBinding

1
2
3
4
5
6
7
8
9
Context 
绑定到  Pod 的  ServiceAccount 的  Role 授予过度宽松的权限。完成以下项目以减少权限集。 
 
Task 
一个名为web-pod的现有Pod已在  namespace db中运行。 
编辑绑定到  Pod 的  ServiceAccount service-account-web的现有Role,仅允许只对  services类型的资源执行  get操作。 
在namespace db中创建一个名为role-2  ,并仅允许只对  namespaces类型的资源执行delete操作的新  Role。 
创建一个名为role-2-binding的新  RoleBinding,将新创建的  Role 绑定到  Pod 的ServiceAccount。 
注意:请勿删除现有的  RoleBinding。 

两个都要看 https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/#role-and-clusterole https://kubernetes.io/zh/docs/reference/access-authn-authz/rbac/#%E4%B8%80%E4%BA%9B%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%B7%A5%E5%85%B7

1680579122337

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# kubectl config use-context KSCH00201 

查看ServiceAccount   service-account-web对应的rolebindings role-1-binding 
查看rolebindings role-1-binding对应的role为role-1 
kubectl describe rolebindings -n db 


编辑role-1权限: 
kubectl edit role role-1 -n db 


修改如下内容 
 
…… 
  resourceVersion: "30867" 
  uid: 22e3c185-f7f5-4542-b86a-6ce153aa1c5a 
rules:   #模拟环境里要删除掉null,然后添加以下内容。考试时,要根据实际情况修改。 
- apiGroups: [""]  
  resources: ["services"]        #只允许对  services资源类型执行  get 操作。还有可能会考只允许对endpoints资源list 的操作
  verbs: ["get"] 
  
 检查 
kubectl describe role role-1 -n db 
在db命名空间,创建名为role-2的role,并且通过rolebinding绑定service-account-web,只允许对namespaces做delete操作。 
记住  --verb是权限,可能考delete或者update等  --resource是对象,可能考namespaces或者persistentvolumeclaims等。 

kubectl create role role-2 --verb=delete --resource=namespaces -n db 
kubectl create rolebinding role-2-binding --role=role-2 --serviceaccount=db:service-account-web -n db 

检查 
kubectl describe rolebindings -n db 

方法二:

1
2
3
4
确认web-pod的pod是否指定service-account-web,再看下对应role是否有对services资源的get操作。 
 
kubectl create role web-role-2 --verb=delete --resource=namespaces -n monitoring 
kubectl create rolebinding web-role-2-binding --role=web-role-2 --serviceaccount=monitoring:service-account-web -n monitoring 

5、日志审计 log audit

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Task 
在cluster中启用审计日志。为此,请启用日志后端,并确保: 
⚫  日志存储在  /var/log/kubernetes/audit-logs.txt 
⚫  日志文件能保留  10⚫  最多保留  2  个旧审计日志文件 
 
/etc/kubernetes/logpolicy/sample-policy.yaml  提供了基本策略。它仅指定不记录的内容。 
注意:基本策略位于cluster的master节点上。 
 
编辑和扩展基本策略以记录: 
⚫  RequestResponse 级别的  persistentvolumes更改 
⚫  namespace front-apps中  configmaps更改的请求体 
⚫  Metadata 级别的所有  namespace 中的  ConfigMap 和  Secret 的更改 
此外,添加一个全方位的规则以在  Metadata 级别记录所有其他请求。 
注意:不要忘记应用修改后的策略。 

https://kubernetes.io/zh/docs/tasks/debug/debug-cluster/audit/

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
# kubectl config use-context KSCH00601

本题分数比较多,占12%。 
 
日志审计这一题需要自己调整的内容还是挺多的,因此要非常仔细,建议修改前备份一下原始的环境,要不然修改错了就会导致集群崩溃。

启用 RequestResponse 级别的审计记录来跟踪 persistentvolumes 更改的请求。
启用 namespace front-apps 中 configmaps 更改请求体的审计记录。
启用 Metadata 级别的审计记录来跟踪所有 namespace 中 ConfigMap 和 Secret 的更改。
添加一个全方位的规则以记录所有其他请求的 Metadata 级别的审计记录。




1 切换到Master的root下 
ssh master01 
sudo -i 

2 配置审计策略 
先备份配置文件 
mkdir bak5 
cp /etc/kubernetes/logpolicy/sample-policy.yaml  bak5/ 
 
vim /etc/kubernetes/logpolicy/sample-policy.yaml 

参考官方网址内容 
 
……
rules: 
  # namespaces changes at RequestResponse level 
  - level: RequestResponse 
    resources: 
    - group: "" 
      resources: ["persistentvolumes"]     #根据题目要求修改,比如题目要求的是namespaces。 
 
  #the request body of persistentvolumes/pods changes in the namespace front-apps 
  - level: Request 
    resources: 
    - group: "" 
      resources: ["configmaps"]       #根据题目要求修改,比如题目要求的是persistentvolumes或者pods。 
    namespaces: ["front-apps"] 
 
  # Log configmap and secret changes in all other namespaces at the Metadata level. 
  - level: Metadata 
    resources: 
    - group: "" 
      resources: ["secrets", "configmaps"] 
   
  # Also, add a catch-all rule to log all other requests at the Metadata level. 
  - level: Metadata 
    omitStages: 
      - "RequestReceived" 
 
 
 
3  配置  master 节点的kube-apiserver.yaml 
先备份配置文件 
mkdir bak5 
cp /etc/kubernetes/manifests/kube-apiserver.yaml  bak5/ 
vi /etc/kubernetes/manifests/kube-apiserver.yaml 

添加以下参数:注意空格要对齐 
#定义审计策略yaml文件位置,通过hostpath挂载 
    - --audit-policy-file=/etc/kubernetes/logpolicy/sample-policy.yaml          #主意检查,如果考试中已经存在了,则不要重复添加。 
#定义审计日志位置,通过hostpath挂载 
    - --audit-log-path=/var/log/kubernetes/audit-logs.txt                     #主意检查,如果考试中已经存在了,则不要重复添加。 
#定义保留旧审计日志文件的最大天数为10天 
    - --audit-log-maxage=10                     #主意检查,如果考试中已经存在了,则不要重复添加。 
#定义要保留的审计日志文件的最大数量为2个 
    - --audit-log-maxbackup=2                          #主意检查,如果考试中已经存在了,则不要重复添加。


#在kube-apiserver.yaml  文件的volumeMounts 标签下增加 
    volumeMounts:     #找到这个字段,添加下面内容 
    - mountPath: /etc/kubernetes/logpolicy/sample-policy.yaml        #这里也可以写到目录/etc/kubernetes/logpolicy/ 
      name: audit     #注意,在1.23考试中,蓝色的内容已经默认有了,你只需要添加绿色字体的内容。可以通过红色字,在文件中定位。但模拟环境没有加,
需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致api-server启不起来。 
      readOnly: true         #这个为true 
    - mountPath: /var/log/kubernetes/ 
      name: audit-log        #注意,在1.23考试中,蓝色的内容已经有了,你只需要添加绿色字体的内容。可以通过红色字,在文件中定位。但模拟环境没有加,
需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。 
      readOnly: false         #这个为false 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#在kube-apiserver.yaml  文件的volumes标签下增加 
  volumes:       #找到这个字段,添加下面内容    #注意,在1.23考试中,蓝色的内容已经有了,volumes这段无需修改,但是为了以防万一,模拟环境中没有
加,需要你手动添加。这样是为了练习,万一考试中没有,你也会加。 
  - name: audit 
    hostPath: 
      path: /etc/kubernetes/logpolicy/sample-policy.yaml     #这里如果写到目录/etc/kubernetes/logpolicy/,则下面的type:应为type: DirectoryOrCreate 
      type: File 
  - name: audit-log 
    hostPath: 
      path: /var/log/kubernetes/ 
      type: DirectoryOrCreate 
      
4  重启kubelet服务 
systemctl restart kubelet 
 
等待2分钟后,再检查 
kubectl get pod -A 
tail /var/log/kubernetes/audit-logs.txt 
 
# 退出root,退回到candidate@master01 
exit 
# 退出master01,退回到candidate@node01 
exit 

6、创建 Secret

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
Task 
在namespace istio-system中获取名为db1-test的现有secret的内容 
 
将username字段存储在名为  /cks/sec/user.txt 的文件中,并将password字段存储在名为  /cks/sec/pass.txt的文件中。 
注意:你必须创建以上两个文件,他们还不存在。 
 
注意:不要在以下步骤中使用/修改先前创建的文件,如果需要,可以创建新的临时文件。 
 
在istio-system namespace中创建一个名为db2-test的新secret,内容如下: 
username :   production-instance 
password :   KvLftKgs4aVH 
 
最后,创建一个新的Pod,它可以通过卷访问secret db2-test  : 
Pod 名称  secret-pod 
Namespace   istio-system 
容器名    dev-container 
镜像  nginx 
卷名  secret-volume 
挂载路径    /etc/secret 

三个网址都要看 https://kubernetes.io/zh/docs/tasks/configmap-secret/managing-secret-using-kubectl/#decoding-secret https://kubernetes.io/zh/docs/tasks/configmap-secret/managing-secret-using-kubectl/#create-a-secret https://kubernetes.io/zh/docs/concepts/configuration/secret/#using-secrets

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# kubectl config use-context KSCH00701 

1  将db1-test的username和password,通过base64解码保存到题目指定文件: 
 
方法1: 
kubectl get secrets db1-test -n istio-system -o jsonpath={.data} 
会反馈结果为:{"password":"aGVsbG8=","username":"ZGIx"} 
echo 'ZGIx'|base64 -d >    /cks/sec/user.txt 
echo 'aGVsbG8='|base64 -d >    /cks/sec/pass.txt 

方法2: 
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 

检查 
cat /cks/sec/user.txt 
cat /cks/sec/pass.txt 

2  创建名为  db2-test 的  secret 使用题目要求的用户名和密码作为键值。注意要加命名空间。 
注意,如果密码中有特殊字符(例如:$,\,*,= 和  !),需要加单引号来转义--from-literal=password='G!Y\*d$zDsb'这样。 
kubectl create secret generic db2-test -n istio-system --from-literal=username=production-instance --from-literal=password=KvLftKgs4aVH 



3  根据题目要求,参考官网,创建Pod使用该secret 
vim k8s-secret.yaml 
添加如下内容 
apiVersion: v1 
kind: Pod 
metadata: 
  name: secret-pod     #pod名字 
  namespace: istio-system      #命名空间 
spec: 
  containers: 
  - name: dev-container      #容器名字 
    image: nginx        #镜像名字 
    volumeMounts:      #挂载路径 
    - name: secret-volume  #卷名 
      mountPath: /etc/secret 
  volumes: 
  - name: secret-volume  #卷名 
    secret: 
      secretName: db2-test   #名为  db2-test 的  secret 
      
  
  创建 
kubectl apply -f k8s-secret.yaml 

7、Dockerfile检测

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Task 
分析和编辑给定的Dockerfile /cks/docker/Dockerfile(基于ubuntu:16.04  镜像), 
并修复在文件中拥有的突出的安全/最佳实践问题的两个指令。 
 
分析和编辑给定的清单文件  /cks/docker/deployment.yaml  , 
并修复在文件中拥有突出的安全/最佳实践问题的两个字段。 
 
注意:请勿添加或删除配置设置;只需修改现有的配置设置让以上两个配置设置都不再有安全/最佳实践问题。 
 
注意:如果您需要非特权用户来执行任何项目,请使用用户ID    65535 的用户  nobody 。 
 
只修改即可,不需要创建。 

https://kubernetes.io/zh/docs/concepts/security/pod-security-standards/#restricted

1680581023970

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# kubectl config use-context KSSC00301 
 
注意,本次的Dockerfile和deployment.yaml仅修改即可,无需部署。


<1>  修改Dockerfile 
vi /cks/docker/Dockerfile 
 
1、仅将CMD上面的USER root修改为USER nobody,不要改其他的USER root。 
USER nobody 
 
2、修改基础镜像为题目要求的  ubuntu:16.04 
FROM ubuntu:16.04 


<2>  修改deployment.yaml 
vi /cks/docker/deployment.yaml 
 
1、template 里标签跟上面的内容不一致,所以需要将原先的run: couchdb 修改为app: couchdb 
                app: couchdb 
(注意,这里具体要改成app: couchdb还是其他的标签,要以考试给你的yaml文件的上下文其他标签为准,要与另外两个标签一致,具体见下方截图。) 
  感谢网友Tse和adams的反馈和纠正。 

2、删除  'SYS_ADMIN' 字段,确保  'privileged':  为False  。(CKS考试是有多套类似考试环境的,所以有时是删SYS_ADMIN,有时是改'privileged': False) 
注意  注意,如果考试时,本来就没有'SYS_ADMIN'  字段,且'privileged':也默认就为False,则直接将下面绿色的这两行注释掉,就是前面加#。 
    securityContext: 
      {'Capabilities': {'add': ['NET_BIND_SERVICE'], 'drop': ['all']}, 'privileged': False, 'readonlyRootFilesystem': False, 'runAsUser': 65535} 
 
修改后 

1680581099534

1680581326781

8、沙箱运行容器 gVisor

1
2
3
4
5
6
7
8
9
Context 
该  cluster使用  containerd作为CRI运行时。containerd的默认运行时处理程序是runc。 
containerd已准备好支持额外的运行时处理程序runsc (gVisor) 
Task 
使用名为runsc的现有运行时处理程序,创建一个名为untrusted 的RuntimeClass。 
更新  namespace server中的所有Pod以在gVisor上运行。 
 
您可以在  /cks/gVisor/rc.yaml中找到一个模版清单

参考资料: https://kubernetes.io/zh/docs/concepts/containers/runtime-class/#2-%E5%88%9B%E5%BB%BA%E7%9B%B8%E5%BA%94%E7%9A%84-runtimeclass-%E8%B5%84%E6%BA%90

1680581426057

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# kubectl config use-context KSMV00301 
 
1 创建RuntimeClass 
vi /cks/gVisor/rc.yaml 
添加如下内容 
…… 
metadata: 
  name: untrusted      # 用来引用  RuntimeClass 的名字,RuntimeClass 是一个集群层面的资源 
handler: runsc      # 对应的  CRI 配置的名称 
 
创建 
kubectl apply -f /cks/gVisor/rc.yaml 
 
检查 
kubectl get RuntimeClass 

2 将命名空间为server下的Pod引用RuntimeClass。 
考试时,3个Deployment下有3个Pod,修改3个deployment即可。 
 
kubectl -n server get deployment 

编辑deployment 
kubectl -n server edit deployments busybox-run 
kubectl -n server edit deployments nginx-host 
kubectl -n server edit deployments run-test 
 
修改如下内容 
    spec:   #找到这个spec,注意在deployment里是有两个单独行的spec的,要找第二个,也就是下面有containers这个字段的spec。 
      runtimeClassName: untrusted    #添加这一行,注意空格对齐,保存会报错,忽略即可。 
      containers: 
      - image: nginx:1.9 
                imagePullPolicy: IfNotPresent 
                name: run-test 
 

因为模拟环境没有安装runsc运行环境,所以改完后,新Pod是ContainerCreating状态。考试时,改完后Pod会重建并Running的。

9、容器安全,删除特权Pod

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Context 
最佳实践是将容器设计为无状态和不可变的。 
 
Task 
检查在  namespace production中运行的Pod,并删除任何非无状态或非不可变的  Pod。 
 
使用以下对无状态和不可变的严格解释: 
⚫  能够在容器内存储数据的  Pod 的容器必须被视为非无状态的。 
注意:你不必担心数据是否实际上已经存储在容器中。 
⚫  被配置为任何形式的特权  Pod 必须被视为可能是非无状态和非不可变的。 
 

https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

`

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# kubectl config use-context KSRS00501 
 
查看此命名空间下的所有  pod,删除有特权  Privileged 或者挂载  volume 的  pod 
kubectl get pod -n production 
kubectl get pods XXXX -n production -o yaml | grep -i "privileged: true"          #注意冒号后面有一个空格,XXXX换成production命名空间下的pod名。 

 将上面查出来的有特权的pod删除 
kubectl delete pod XXXX -n production 



上面只是将特权的pod查出来了,根据题目要求,还应该查挂载volume的pod,命令为 
kubectl get pods XXXX -n production -o jsonpath={.spec.volumes} | jq 
模拟环境里的3个pod,都没有挂载volume,所以无需删除了。考试中也是这样的,都没有挂载volume。 

1680581731355

什么样的是挂载了volume的pod呢? 比如kube-system命名空间下的etcd-master01是挂载了volume的。 具体是否挂载,可以依据是否有hostPath或路径

1680581744418

10、网络策略 NetworkPolicy

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Task 
创建一个名为pod-restriction  的NetworkPolicy来限制对在namespace dev-team 中运行的Pod products-service的访问。 
 
只允许以下Pod连接到Pod products-service 
⚫  namespace qaqa中的Pod 
⚫  位于任何namespace,带有标签environment: testing的Pod 
 
注意:确保应用NetworkPolicy。 
 
你可以在/cks/net/po.yaml找到一个模板清单文件。 

https://kubernetes.io/zh/docs/concepts/services-networking/network-policies/#networkpolicy-resource

1680588050517

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# kubectl config use-context KSSH00301 
 
1  检查namespace标签 
 
模拟环境已提前打好标签了,所以你只需要检查标签即可。但为了防止考试时,没有给你打标签,所以还是需要你将下面打标签的命令记住。 
# 查看  qaqa  命名空间标签(name: qaqa) 
kubectl get ns --show-labels 

# 查看  pod 标签(environment: testing) 
kubectl get pod -n dev-team --show-labels 


如果  Pod 或者  Namespace 没有标签,则需要打上标签。 
注意:我这里将pod products-service的标签打成了environment: testing,下面会有解释,不要和题目里要求的“位于任何 namespace,带有标签environment: 
testing的Pod”这句话里的标签混淆了。 
# kubectl label ns qaqa name=qaqa 
# kubectl label pod products-service environment=testing -n dev-team 


  创建NetworkPolicy 
 
vi /cks/net/po.yaml 
根据官网,修改为如下内容: 
…… 
metadata: 
  name: pod-restriction      #修改 
  namespace: dev-team          #修改 
spec: 
  podSelector: 
    matchLabels: 
      environment: testing       #根据题目要求的标签修改,这个写的是Pod    products-service的标签,也就是使用kubectl get pod -n dev-team --show-labels 查出来的pod的标签,这个标签不要和题目里要求的“位于任何namespace,带有标签environment: testing的Pod”这句话里的标签混淆了,两个没有关系,所以可不一样。比如你考试时查出来的POD   products-service的标签是name: products,那这里的environment: testing就要换成name: products。 
  policyTypes: 
  - Ingress        #注意,这里只写  - Ingress,不要将  - Egress也复制进来! 
  ingress: 
  - from:        #第一个from 
    - namespaceSelector: 
                matchLabels: 
                   name: qaqa        #命名空间有name: qaqa标签的 
  - from:        #第二个from 
    - namespaceSelector: {}  #修改为这样,所有命名空间 
      podSelector:      #注意,这个podSelector前面的“-” 要删除,换成空格,空格对齐要对。 
                matchLabels: 
                   environment: testing     #有environment: testing标签的Pod,这个地方是根据题目要求“Pods with label environment: testing , in any namespace”,这句话里的pod标签写的。不要和上面spec里的混淆。
                   
                   
   
创建 
kubectl apply -f /cks/net/po.yaml 
 
检查 
kubectl get networkpolicy -n dev-team 

11、Trivy 扫描镜像安全漏洞

1
2
3
4
5
6
7
8
9
Task 
使用Trivy开源容器扫描器检测namespace kamino中  Pod 使用的具有严重漏洞的镜像。 
 
查找具有High或Critical严重性漏洞的镜像,并删除使用这些镜像的Pod。 
 
注意:Trivy仅安装在cluster的master节点上, 
在工作节点上不可使用。 
你必须切换到cluster的master节点才能使用Trivy。 
 

https://kubernetes.io/zh/docs/reference/kubectl/cheatsheet/#%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%BE%93%E5%87%BA

1
2
# 列举 default 名字空间中运行的所有镜像,按 Pod 分组
kubectl get pods --namespace default --output=custom-columns="NAME:.metadata.name,IMAGE:.spec.containers[*].image"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# kubectl config use-context KSSC00401 

注意:这个题非常耗费时间,考试时关注一下剩余时间。如果时间剩余不多,可以放到最后做这道题。 

1 切换到Master的candidate下 
ssh master01 
 
 
 
2  获取命名空间kamino  下的所有pod的image 
kubectl get pods --namespace kamino --output=custom-columns="NAME:.metadata.name,IMAGE:.spec.containers[*].image" 
# 获取每一个pod的image 
kubect get pod XXXX -n kamino -o yaml | grep image 
 
 
 
 
 
trivy image -s HIGH,CRITICAL nginx:1.19   # HIGH,CRITICAL,这里的nginx:1.19 换成你上一步查出来的镜像名字 
或者也可以使用这条命令查询trivy image nginx:1.19 | grep -iE 'High|Critical' 
注意tri222和tri333的2个pod里各有2个image,都需要扫描。 
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 


4  删除有问题的pod 
kubectl delete pod XXXX -n kamino 
 
 
5 退出master01,退回到candidate@node01 
exit 
 
 
请注意,考试时有5个pod,每个pod里有多个image 镜像,都需要扫描。扫描出有漏洞的镜像,则删除有这个镜像的pod。 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#  切换到Master的root下 
(写while脚本有点麻烦) 
(对于pod数量多的情况,可以使用下面方法) 

ssh master01 
 
检查所有pod 
kubectl get po -n kamino 
kubectl get po -n kamino | grep -v "NAME" | awk '{print $1}' > podlist.txt 
cat podlist.txt 
 
循环检查pod里的image 
while read line;do 
echo $line 
kubectl get pod -n kamino $line -o yaml | grep "image:" 
done < podlist.txt 
 
对查出来的image 逐一扫描 
trivy image -s HIGH,CRITICAL nginx:1.19    #注意HIGH,CRITICAL为大写 
 
删除扫描的镜像带有高危或严重漏洞的  Pod 
kubectl delete pod XXXX -n kamino 
 
 
 
# 退出master01,退回到candidate@node01 
exit 
 

12、AppArmor

1
2
3
4
5
6
Context 
APPArmor 已在  cluster 的工作节点node02上被启用。一个  APPArmor 配置文件已存在,但尚未被实施。 
Task 
在  cluster 的工作节点node02上,实施位于  /etc/apparmor.d/nginx_apparmor的现有APPArmor 配置文件。 
编辑位于  /cks/KSSH00401/nginx-deploy.yaml  的现有清单文件以应用  AppArmor 配置文件。 
最后,应用清单文件并创建其中指定的  Pod 。 

https://kubernetes.io/zh/docs/tutorials/security/apparmor/#example

1680589163772

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# kubectl config use-context KSSH00401 
 
1 切换到node02的root下 
ssh node02 
sudo -i 
 
 
 
 
2 切换到apparmor的目录,并检查配置文件 
cd /etc/apparmor.d/ 
vi /etc/apparmor.d/nginx_apparmor 
注意,nginx-profile-3这一行要注释掉,但要确保profile nginx-profile-3这一行没有注释。 
#include <tunables/global> 
# nginx-profile-3    #注释掉    模拟环境里多写了一行的,会导致apparmor_parser -q的时候会报错。1.21里,这个文件是有一个这样的操作的,但在新的1.23
的考试中,这个/etc/apparmor.d/nginx_apparmor又变成正确的了。所以你在考试时,可以先cat /etc/apparmor.d/nginx_apparmor,有错误则改,没错误,则
不要再改了。 
profile nginx-profile-3 flags=(attach_disconnected) {       #这句是正确的配置,不要修改。profile后面的nginx-profile-3为apparmor策略模块的名字。 
  #include <abstractions/base> 
  file, 
…… 

3  执行apparmor策略模块 
没有grep到,说明没有启动。 
apparmor_status | grep nginx-profile-3 
加载启用这个配置文件 
apparmor_parser -q /etc/apparmor.d/nginx_apparmor 
 
#  再次检查有结果了 
apparmor_status | grep nginx 
显示如下内容 
   nginx-profile-3 
 
 
 4 修改pod文件 
vi /cks/KSSH00401/nginx-deploy.yaml 
修改如下内容 
…… 
metadata: 
  name: podx 
  #添加annotations,kubernetes.io/podx名字和containers下的名字一样即可,nginx-profile-3为前面在worker node01上执行的apparmor策略模块的名
字。 
  annotations: 
     container.apparmor.security.beta.kubernetes.io/podx: localhost/nginx-profile-3 
spec: 
  containers: 
  - image: busybox 
    imagePullPolicy: IfNotPresent 
    name: podx             #这个就是containers下的名字,为podx 
    command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ] 
…… 
 
 
创建 
kubectl apply -f /cks/KSSH00401/nginx-deploy.yaml 


 
# 退出root,退回到candidate@node02 
exit 
# 退出node02,退回到candidate@node01 
exit 
 

13、Sysdig & falco

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Task: 
使用运行时检测工具来检测  Pod tomcat123单个容器中频发生成和执行的异常进程。 
有两种工具可供使用: 
⚫   sysdig 
⚫   falco 
注:  这些工具只预装在cluster的工作节点node02上,不在  master 节点。 
 
使用工具至少分析30秒  ,使用过滤器检查生成和执行的进程,将事件写到  /opt/KSR00101/incidents/summary文件中,   
其中包含检测的事件,  格式如下: 
timestamp,uid/username,processName 


 保持工具的原始时间戳格式不变。 
注:  确保事件文件存储在集群的工作节点上。 
 
请注意,考试时,考题里已表明sysdig在工作节点上,所以你需要ssh到开头写的工作节点上。但在模拟环境,你需要ssh到node02这个工作节点。 



# kubectl config use-context KSSC00401 
1 切换到node02的root下 
ssh node02 
sudo -i 
 
 
 
 
2、先找到containerd的socket 
crictl info | grep sock 

 3、crontainerd要使用crictl命令找到容器,题目要求的是tomcat123,则grep tomcat123。 
crictl ps | grep tomcat123 

4、 
通过  sysdig 扫描容器30s并输出到指定文件: 
sysdig -h  和-l  查看帮助 
注:可以使用  sysdig -l |grep time  过滤,确认输出格式字段 
sysdig -l | grep time 
sysdig -l | grep uid 
sysdig -l | grep proc 
 
开始扫描    (我目前想不到别的方法,只能将命令分成2条了,谁有更好的方法,可以分享一下。) 
sysdig -M 30 -p "%evt.time,%user.uid,%proc.name" --cri /run/containerd/containerd.sock container.name=tomcat123 >> /opt/KSR00101/incidents/summary 
sysdig -M 30 -p "%evt.time,%user.name,%proc.name" --cri /run/containerd/containerd.sock container.name=tomcat123 >> /opt/KSR00101/incidents/summary 
 
提示:如果考试时执行sysdig报错“Unable to load the driver”,则执行下面一条命令:(模拟环境里不需要执行) 
#启用模块 
sysdig-probe-loader 
然后再次执行sysdig -M 30 …… 
如果还是报错,就重装一下sysdig,命令为apt install sysdig 
 
查看保存的文件 
cat /opt/KSR00101/incidents/summary |head 


# 退出root,退回到candidate@node02 
exit 
# 退出node02,退回到candidate@node01 
exit 
 

14、Pod 安全策略-PSP

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Context 
PodSecurityPolicy应防在特定namespace中特权Pod的创建。 
 
Task 
创建一个名为restrict-policy的新的PodSecurityPolicy,以防止特权Pod的创建。 
创建一个名为restrict-access-role并使用新创建的PodSecurityPolicy restrict-policy的ClusterRole。 
在现有的namespace staging中创建一个名为psp-denial-sa的新ServiceAccount 
最后,创建一个名为dany-access-bind的ClusterRoleBinding , 
将新创建的ClusterRole restrict-access-role绑定到新创建的ServiceAccount psp-denial-sa。 
 
你可以在一下位置找到模版清单文件: 
/cks/psp/psp.yaml 
 

四个都要看 https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-apiserver/#%E9%80%89%E9%A1%B9

https://kubernetes.io/docs/concepts/security/pod-security-policy/#create-a-policy-and-a-pod

https://kubernetes.io/docs/concepts/security/pod-security-policy/#via-rbac 如果使用命令不会创建clusterrole和clusterrolebinding,则可以参考官网的yaml文件,修改并使用kubectl apply -f来创建。

https://kubernetes.io/docs/concepts/security/pod-security-policy/#example 使用命令创建clusterrole和clusterrolebinding的参考方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# kubectl config use-context KSMV00102 
 
1 切换到Master的root下 
ssh master01 
sudo -i 
 
 
 
 
2  检查确认apiserver支持PodSecurityPolicy 
启用PSP准入控制器(考试中默认已经启用,但以防万一,还是要检查一下的。) 
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep PodSecurityPolicy 
确保有下面这行,在1.23的考试中,这一行已经提前给你加上了,但还是需要检查确认一下。 
    - --enable-admission-plugins=NodeRestriction,PodSecurityPolicy 
 
 如果kube-apiserver.yam配置文件需要修改 
则先备份配置文件,再添加这行。 
mkdir bak14 
cp /etc/kubernetes/manifests/kube-apiserver.yaml bak14 
vi /etc/kubernetes/manifests/kube-apiserver.yaml 
 
修改或添加如下内容 
    - --enable-admission-plugins=NodeRestriction,PodSecurityPolicy 
 
编辑完后重新加载配置文件,并重启kubelet 
systemctl daemon-reload 
systemctl restart kubelet.service 


# 退出root,退回到candidate@master01 
exit 
# 退出master01,退回到candidate@node01 
exit 

3  创建PSP 
官方网址里复制PSP的内容,并修改拒绝特权。(考试中会给出参考的yaml文件,可以修改这个文件。) 
创建名为prevent-psp-policy的PodSecurityPolicy,阻止创建Privileged Pod。 
vi /cks/psp/psp.yaml            #如果这个文件考试时,在node01找不到,就回上面的master里找。 
修改如下内容 
…… 
metadata: 
  name: restrict-policy   #检查一下name,如果不对则修改。 
spec: 
  privileged: false    # 修改为false,阻止创建Privileged Pod(特权pod) 
  seLinux:       #下面这些信息,根据官网拷贝。 
    rule: RunAsAny 
  supplementalGroups: 
    rule: RunAsAny 
  runAsUser: 
    rule: RunAsAny 
  fsGroup: 
    rule: RunAsAny 
  volumes: 
  - '*' 
 
创建 
kubectl apply -f /cks/psp/psp.yaml 
 
检查 
kubectl get podsecuritypolicy 


4  创建CluserRole和ServiceAccount,并通过ClusterRoleBinding绑定。 
方法1: 
使用命令创建 
kubectl create clusterrole restrict-access-role --verb=use --resource=psp --resource-name=restrict-policy 
kubectl create sa psp-denial-sa -n staging 
kubectl create clusterrolebinding dany-access-bind --clusterrole=restrict-access-role --serviceaccount=staging:psp-denial-sa 

方法2: 

1.23考试中,已经给你3个空的yaml文件了,所以可以使用方法2来做,先修改yaml文件,再apply。 
参考官网,通过yaml文件来创建,CluserRole和ServiceAccount,以及ClusterRoleBinding绑定 
https://kubernetes.io/zh/docs/concepts/policy/pod-security-policy/#via-rbac 

检查 
kubectl describe clusterrolebinding dany-access-bind 
 

15、启用API server认证

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Context 
由  kubeadm 创建的  cluster 的  Kubernetes API 服务器,出于测试目的, 
临时配置允许未经身份验证和未经授权的访问,授予匿名用户  cluster-admin 的访问权限. 
 
Task 
重新配置cluster 的Kubernetes APl 服务器,以确保只允许经过身份验证和授权的  REST请求。 
使用授权模式  Node,RBAC  和准入控制器  NodeRestriction。 
删除用户  system:anonymous  的  ClusterRoleBinding来进行清理。 
 注意:所有kubectl 配置环境/文件也被配置使用未经身份验证和未经授权的访问。 
你不必更改它,但请注意,一旦完成  cluster 的安全加固,  kubectl 的配置将无法工作。 
您可以使用位于  cluster 的  master 节点上,cluster 原本的  kubectl 配置文件 
/etc/kubernetes/admin.conf ,以确保经过身份验证的授权的请求仍然被允许。 

https://kubernetes.io/zh/docs/reference/command-line-tools-reference/kube-apiserver/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# kubectl config use-context KSCF00301 
 
 
1 切换到Master的root下 
ssh master01 
sudo -i

2  确保只有认证并且授权过的REST请求才被允许 
编辑/etc/kubernetes/manifests/kube-apiserver.yaml,修改下面内容 
- --authorization-mode=AlwaysAllow 
- --enable-admission-plugins=AlwaysAdmit 
 
vi /etc/kubernetes/manifests/kube-apiserver.yaml 
修改为 
- --authorization-mode=Node,RBAC                             #注意,只保留Node,RBAC这两个,中间是英文状态下的逗号。在1.23考试中,这一条可能默认已经有
了,但还是要检查确认一下。 
- --enable-admission-plugins=NodeRestriction           #在1.23考试中,这一个原先为AlwaysAdmit,需要修改为NodeRestriction。 
- --client-ca-file=/etc/kubernetes/pki/ca.crt     #这一条也要检查一下,是否存在配置文件中,如果没有,也需要添加。在1.23考试中,这一条默认已经有了。 
- --enable-bootstrap-token-auth=true               #这一条也要检查一下,是否存在配置文件中,如果没有,也需要添加。在1.23考试中,这一条默认已经有
了。 

重启kubelet 
systemctl daemon-reload 
systemctl restart kubelet

修改完成后,等待3分钟,集群才会恢复正常。 
kubectl get pod -A 
 


3 删除题目要求的角色绑定 
kubectl get clusterrolebinding system:anonymous 

kubectl delete clusterrolebinding system:anonymous 
再检查 
kubectl get clusterrolebinding system:anonymous 

16、ImagePolicyWebhook容器镜像扫描

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
cluster上设置了容器镜像扫描器,但尚未完全集成到  cluster 的配置中。 
完成后,容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用。 
 
Task 
注意:你必须在  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来测试配置是否有效。 

三个网址都要看 https://kubernetes.io/zh/docs/reference/access-authn-authz/admission- controllers/#%E5%A6%82%E4%BD%95%E5%90%AF%E7%94%A8%E4%B8%80%E4%B8%AA%E5%87%86%E5%85%A5%E6%8E%A7%E5%88%B6%E5%99%A8

https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/#imagepolicywebhook

https://kubernetes.io/zh/docs/tasks/debug/debug-cluster/audit/#log-%E5%90%8E%E7%AB%AF

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# kubectl config use-context KSSH00901 
 
本题分数比较多,占10% 
 
第1步  切换到Master的root下 
ssh master01 
sudo -i 

第2步,编辑admission_configuration.json(题目会给这个目录),修改defaultAllow为false: 
vi /etc/kubernetes/epconfig/admission_configuration.json 
 
…… 
     "denyTTL": 50, 
     "retryBackoff": 500, 
     "defaultAllow": false   #将true改为false 
…… 
 
第3步,编辑/etc/kubernetes/epconfig/kubeconfig.yml,添加  webhook server 地址: 
操作前,先备份配置文件 
mkdir bak16 
cp /etc/kubernetes/epconfig/kubeconfig.yml  bak16/ 
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 
…… 
 
 
 第4步,编辑kube-apiserver.yaml,从官网中引用  ImagePolicyWebhook  的配置信息: 
操作前,先备份配置文件 
mkdir bak16 
cp /etc/kubernetes/manifests/kube-apiserver.yaml   bak16/ 
vi /etc/kubernetes/manifests/kube-apiserver.yaml 
在- command:下添加如下内容,注意空格要对齐 
    - --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook 
    - --admission-control-config-file=/etc/kubernetes/epconfig/admission_configuration.json    #在1.23的考试中,默认这行已经添加了,但为了以防万一,
模拟环境,没有添加,需要你手动添加。考试时,你先检查,有的话,就不要再重复添加了。重复添加反而会报错! 


# 在kube-apiserver.yaml的  volumeMounts 增加 
    volumeMounts:     #在volumeMounts下面增加    #注意,在1.23考试中,蓝色的内容可能已经有了,你只需要添加绿色字体的内容。可以通过红色字,在文件中定位。但模拟环境没有加,需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致api-server启不起来。 
    - mountPath: /etc/kubernetes/epconfig 
      name: epconfig 
      readOnly: true 
 
 
  
# 在kube-apiserver.yaml的volumes 增加 
  volumes:     #在volumes下面增加    #注意,在1.23考试中,蓝色的内容可能已经有了,你只需要检查确认一下是否准确。可以通过红色字,在文件中定位。但模拟环境没有加,需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致api-server启不起来。 
  - name: epconfig 
    hostPath: 
      path: /etc/kubernetes/epconfig 
      type: DirectoryOrCreate 
#如果你写的是目录,则是DirectoryOrCreate,如果你写的是文件,则是File 


第5步,重启kubelet。 
systemctl restart kubelet 
 
通过尝试部署易受攻击的资源  /cks/img/web1.yaml来测试配置是否有效 
无法创建pod,如下报错,表示成功。 
因为模拟环境里的image_policy 策略是镜像tag是latest 的不允许创建。 
kubectl apply -f /cks/img/web1.yaml 


第6步  退回到原ssh终端 
# 退出root,退回到candidate@master01 
exit 
# 退出master01,退回到candidate@node01 
exit