CKS环境搭建和题库

test

1.创建 Secret

环境准备:

kubectl create namespace istio-system
kubectl create secret generic test-app --namespace istio-system --from-literal=username=test --from-literal=password=123456

参考资料:
三个网址都要看

您必须在以下 cluster /节点上完成此考题

Cluster Master 节点 工作节点
KSMV00201 ksmv00201-master ksmv00201-worker1

您可以使用以下命令来切换 cluster / 配置环境:
[candidate@cli] $ kubectl config use-context KSMV00201

Task
在namespace istio-system 中获取名为 test-app 的现有 secret 的内容。


将 username 字段存储在名为 /home/candidate/user.txt 的文件中,
并将password 字段存储在名为 /home/candidate/password.txt 的文件中。

您必须创建以上两个文件; 它们还不存在

==不要在以下步骤中使用/修改先前创建的文件,如果需要创建新的临时文件。==


istio-system namespace 中创建一个名为 test-workflow 的新 secret,
内容如下:

username: dev-database
password: aV7HR7nU3JLx

最后,创建一个新的 Pod,它可以通过卷访问 secret test-workflow :

Pod名 test-secret-pod
Namespace istio-system
容器名 dev-container
镜像 nginx
卷名 secret-volume
挂载路径 /etc/secret

答题步骤:

1 将 test-app 的 username 和 password,通过 base64 解码保存到题目指定文件:
#方法 1:
root@cka-master01:~# kubectl get secrets test-app -n istio-system -o jsonpath={.data}
{"password":"MTIzNDU2","username":"dGVzdA=="}r
mkdir /home/candidate/ -pv
echo 'dGVzdA=='|base64 -d > /home/candidate/user.txt 
echo 'MTIzNDU2'|base64 -d > /home/candidate/password.txt

#方法 2:
mkdir /home/candidate/ -pv
kubectl get secrets -n istio-system test-app -o jsonpath={.data.username} | base64 -d > /home/candidate/user.txt 
kubectl get secrets -n istio-system test-app -o jsonpath={.data.password} | base64 -d > /home/candidate/password.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 test-workflow -n istio-system --from-literal=username=dev-database --from-literal=password=aV7HR7nU3JLx
#检查
root@cka-master01:~# kubectl get secret -n istio-system test-workflow
NAME            TYPE     DATA   AGE
test-workflow   Opaque   2      25s


3 根据题目要求,参考官网,创建 Pod 使用该 secret
vim k8s-secret.yaml
#添加如下内容
apiVersion: v1
kind: Pod
metadata:
 name: test-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: test-workflow #名为 test-workflow 的 secret

#创建
kubectl apply -f k8s-secret.yaml
#检查
root@cka-master01:~# kubectl get pod -n istio-system
NAME              READY   STATUS    RESTARTS   AGE
test-secret-pod   1/1     Running   0          4s

2.ImagePolicyWebhook (准入控制器)容器镜像扫描

环境准备:

mkdir /etc/kubernetes/controlconf -pv
cd /etc/kubernetes/controlconf

wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssl_1.6.0_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.0/cfssljson_1.6.0_linux_amd64
chmod +x cfssl* 
mv cfssl_1.6.0_linux_amd64 /usr/local/bin/cfssl
mv cfssljson_1.6.0_linux_amd64 /usr/local/bin/cfssljson

cat << EOF | cfssl  genkey - | cfssljson -bare server
{
  "hosts": [
    "acme.local",
    "acme.local.svc.cluster.local",
    "acme.local.pod.cluster.local",
    "172.22.136.223",
    "10.244.1.0/24"
  ],
  "CN": "system:node:acme.local.pod.cluster.local",
  "key": {
    "algo": "ecdsa",
    "size": 256
  },
  "names": [
    {
      "O": "system:nodes"
    }
  ]
}
EOF

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: acme.local
spec:
  request: $(cat server.csr | base64 | tr -d '\n')
  signerName: kubernetes.io/kubelet-serving
  usages:
  - digital signature
  - key encipherment
  - server auth
EOF

kubectl get csr|grep 'Pending'| awk 'NR>0{print $1}' |xargs kubectl certificate approve
kubectl get csr acme.local -o jsonpath='{.status.certificate}' | base64 --decode > server.crt

kubectl create namespace local

kubectl create secret tls tls-acme --key /etc/kubernetes/controlconf/server-key.pem --cert /etc/kubernetes/controlconf/server.crt --namespace local

cat << EOF > /etc/kubernetes/controlconf/image-bouncer-webhook.yaml
apiVersion: v1
kind: Service
metadata:
  labels:
    app: acme
  name: acme
  namespace: local
spec:
  ports:
    - name: https
      port: 8082
      targetPort: 1323
      protocol: "TCP"
  selector:
    app: acme
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: acme
  namespace: local
spec:
  selector:
    matchLabels:
      app: acme
  template:
    metadata:
      labels:
        app: acme
    spec:
      containers:
        - name: image-bouncer-webhook
          imagePullPolicy: Always
          image: "kainlite/kube-image-bouncer:latest"
          args:
            - "--cert=/etc/admission-controller/tls/tls.crt"
            - "--key=/etc/admission-controller/tls/tls.key"
            - "--debug"
          volumeMounts:
            - name: tls
              mountPath: /etc/admission-controller/tls
      volumes:
        - name: tls
          secret:
            secretName: tls-acme     # Webhook 证书的 tls 密钥 和密钥
EOF
kubectl apply -f /etc/kubernetes/controlconf/image-bouncer-webhook.yaml


echo $(kubectl get service -n local acme -o jsonpath='{.spec.clusterIP}') acme.local >> /etc/hosts


cat << EOF >> /etc/kubernetes/controlconf/kubeconfig.yml
apiVersion: v1
kind: Config
clusters:
- cluster:
    certificate-authority: /etc/kubernetes/controlconf/server.crt
    server: server
  name: bouncer_webhook
contexts:
- context:
    cluster: bouncer_webhook
    user: api-server
  name: bouncer_validator
current-context: bouncer_validator
preferences: {}
users:
- name: api-server
  user:
    client-certificate: /etc/kubernetes/pki/apiserver.crt
    client-key:  /etc/kubernetes/pki/apiserver.key
EOF

cat << EOF >> /etc/kubernetes/controlconf/admission_configuration.json 
{
  "imagePolicy": {
     "kubeConfigFile": "/etc/kubernetes/controlconf/kubeconfig.yml",
     "allowTTL": 50,
     "denyTTL": 50,
     "retryBackoff": 500,
     "defaultAllow": true
  }
}
EOF

mkdir /root/KSSC00202
cat << EOF >> /root/KSSC00202/configuration-test.yml
apiVersion: v1
kind: ReplicationController
metadata:
  name: nginx-latest
spec:
  replicas: 1
  selector:
    app: nginx-latest
  template:
    metadata:
      name: nginx-latest
      labels:
        app: nginx-latest
    spec:
      containers:
      - name: nginx-latest
        image: nginx    # 不写标签默认是nginx:latest
        ports:
        - containerPort: 80
EOF

参考资料: 三个网址都要看

您必须在以下 cluster群 彪啊傍佬嫡尺节点上完成此考题:
Cluster Master 节点 工作节点
KSSC00202 kssc00202-master kssc00202-worker1

您可以使用以下命今来切换 cluster /配置环境
[candidate@cli] $ kubectl config use-context KSSCO0202

Context
cluster 上设置了容器镜像扫描器,但尚未完全集成到 cluster 的配置中。完成后,容器镜像扫描器应扫描并拒绝易受攻击的镜像的使用。

Task

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

给定一个目录 /etc/kubernetes/controlconf 中不完整的配置以及具有HTTPS 端点 https://acme.local:8082/image_policy
的功能性容器镜像扫描器:

  1. 启用必要的插件来创建镜像策略
  2. 校验控制配置并将其更改为隐式拒绝(implicit deny)
  3. 编辑配置以正确指向提供的 HTTPS 端点

最后,通过尝试部署易受攻击的资源
/root/KSSC00202/configuration-test.yml 来测试配置是否有效

==您可以在 /var/log/imagepolicy/wakanda.log 找到容器镜像扫描仪的日志文件。==

答题步骤:

本题分数比较多,占 10%
第 1 步 切换到 Master 的 root 下
ssh master01
sudo -i

第 2 步,编辑 admission_configuration.json(题目会给这个目录),修改 defaultAllow 为 false:
vi /etc/kubernetes/controlconf/admission_configuration.json
……
 "denyTTL": 50,
 "retryBackoff": 500,
 "defaultAllow": false #将 true 改为 false
……

第 3 步,编辑/etc/kubernetes/controlconf/kubeconfig.yml,添加 webhook server 地址:
#操作前,先备份配置文件
mkdir backup
cp /etc/kubernetes/controlconf/kubeconfig.yaml backup/
vi /etc/kubernetes/controlconf/kubeconfig.yaml
#修改如下内容
……
   certificate-authority: /etc/kubernetes/controlconf/ca.crt
   server: https://acme.local:8082/image_policy #添加 webhook server 地址
 name: image-checker
……

第 4 步,编辑 kube-apiserver.yaml,从官网中引用 ImagePolicyWebhook 的配置信息:
#操作前,先备份配置文件
mkdir backup
cp /etc/kubernetes/manifests/kube-apiserver.yaml backup/
vi /etc/kubernetes/manifests/kube-apiserver.yaml
#在- command:下添加如下内容,注意空格要对齐
 - --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
 - --admission-control-config-file=/etc/kubernetes/controlconf/admission_configuration.json #在 1.23 的考试中,默认这行已经添加了,但为了以防万一,模拟环境,没有添加,需要你手动添加。考试时,你先检查,有的话,就不要再重复添加了。重复添加反而会报错!
# 在 kube-apiserver.yaml 的 volumeMounts 增加
 volumeMounts: #在 volumeMounts 下面增加 #注意,在 1.23 考试中,蓝色的内容可能已经有了,你只需要添加绿色字体的内容。可以通过红色字,在文件中定位。但模拟环境没有加,需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致 api-server 启不起来。
 - mountPath: /etc/kubernetes/controlconf
   name: kubeconfig
   readOnly: true 
 # 在 kube-apiserver.yaml 的 volumes 增加
 volumes: #在 volumes 下面增加 #注意,在 1.23 考试中,蓝色的内容可能已经有了,你只需要检查确认一下是否准确。可以通过红色字,在文件中定位。
#但模拟环境没有加,需要你全部手动添加。这样是为了练习,万一考试中没有,你也会加。但是如果考试中已添加,你再添加一遍,则会报错,导致 api-server启不起来。
 - name: kubeconfig
   hostPath:
     path: /etc/kubernetes/controlconf
     type: DirectoryOrCreate
#如果你写的是目录,则是 DirectoryOrCreate,如果你写的是文件,则是 File

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

第 6 步 退回到原 ssh 终端
# 退出 root,退回到 candidate@master01
exit
# 退出 master01,退回到 candidate@node01
exit
3.网络策略 NetworkPolicy

环境准备:

mkdir /home/candidate/KSSHO0301 -pv
cat << EOF >> /home/candidate/KSSHO0301/network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: multi-port-egress
  namespace: default
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
    - Egress
  egress:
    - to:
        - ipBlock:
            cidr: 10.0.0.0/24
      ports:
        - protocol: TCP
          port: 32000
          endPort: 32768
EOF

kubectl create namespace development

参考资料:

Quick Reference
文档 NetworkPolicyPodNamespace

您必须在以下 cluster /节点上完成此考题

Cluster Master 节点 工作节点
KSSH00301 kssh00301-master kssh00301-worker1

您可以使用以下命今来切换 cluster /配置环境
[candidate@cli] $ kubectl config use-context KSSHO0301

Task
创建一个名为 pod-restriction 的 NetworkPolicy 来限制对在 namespace development 中运行的 Pod users-service 的访问

只允许以下 Pod 连接到 Pod users-service :

  • namespace qa 中的 Pod
  • 位于任何 namespace ,带有标签 environment: staging 的 Pod

==确保应用 NetworkPolicy 。==
==你可以在 /home/candidate/KSSHO0301/network-policy.yaml 找到个模板清单文件。==

答题步骤:

1 检查 namespace 标签
#模拟环境已提前打好标签了,所以你只需要检查标签即可。但为了防止考试时,没有给你打标签,所以还是需要你将下面打标签的命令记住。
# 查看 qaqa 命名空间标签(name: qaqa)
kubectl get ns --show-labels

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

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

2 创建 NetworkPolicy
vi /home/candidate/KSSHO0301/network-policy.yaml
#根据官网,修改为如下内容:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: pod-restriction #修改
  namespace: development #修改
spec:
  podSelector:
    matchLabels:
      environment: staging #根据题目要求的标签修改,这个写的是 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: qa #命名空间有 name: qaqa 标签的
  - from: #第二个 from
    - namespaceSelector: {} #修改为这样,所有命名空间
       podSelector: #注意,这个 podSelector 前面的“-” 要删除,换成空格,空格对齐要对。
         matchLabels:
           environment: staging #有 environment: testing 标签的 Pod,这个地方是根据题目要求“Pods with label environment: testing , in any namespace”,这句话里的 pod 标签写的。不要和上面 spec 里的混淆。

#创建
kubectl apply -f /home/candidate/KSSHO0301/network-policy.yaml
#检查
kubectl get networkpolicy -n dev-team
4.沙箱运行容器 gVisor

环境准备:

mkdir /home/candidate/KSMV00301 -pv
cat << EOF > /home/candidate/KSMV00301/runtime-class.yaml
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: myclass
handler: mycofiguration
EOF

kubectl create namespace client
kubectl create deployment busybox-run --image nginx --namespace client 
kubectl create deployment nginx-host --image nginx --namespace client 
kubectl create deployment run-test --image nginx --namespace client 

参考资料:

Quick Reference
文档 RuntimeClassPodNamespace

您必须在以下 cluster /节点上完成此考题
Cluster Master 节点 工作节点
KSMV00301 ksmv00301-master ksmv00301-worker1

您可以使用以下命令来切换 cluster / 配置环境:
[candidate@cli] $ kubectl config use-context KSMV00301

Context
该 cluster 使用 containerd 作为 CRI运行时。containerd的默认运行时处理程序是 runccontainerd 已准备好支持额外的运行时处理程序 runsc ( gVisor ) 。

Task
使用名为 runsc 的现有运行时处理程序,创建一个名为 untrusted 的RuntimeClass .

更新 namespace client 中的所有 Pod 以在gVisor 上运行

==你可以在 /home/candidate/KSMV00301/runtime-class.yaml找到一个模板清单文件。==

答题步骤:

1 创建 RuntimeClass
vi /home/candidate/KSMV00301/runtime-class.yaml
#修改如下内容
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: untrusted  # 用来引用 RuntimeClass 的名字,RuntimeClass 是一个集群层面的资源
handler: runsc  # 对应的 CRI 配置的名称

#创建
kubectl apply -f /home/candidate/KSMV00301/runtime-class.yaml
#检查
root@cka-master01:~# kubectl get runtimeclasses.node.k8s.io
NAME        HANDLER   AGE
untrusted   runsc     8s


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

#编辑 deployment
kubectl -n client edit deployments busybox-run
kubectl -n client edit deployments nginx-host
kubectl -n client 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 的
5.Pod指定ServiceAccount

准备环境:

mkdir /home/candidate/KSCHO0301/ -pv
kubectl create namespace dev
kubectl create serviceaccount test01 --namespace dev

cat << EOF >> /home/candidate/KSCH00301/pod-manifest.yaml
apiVersion: v1
kind: Pod
metadata:
  name: backend
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - name: nginx
      targetPort: 80
EOF
Quick Reference
文档 ServiceAccountPodNamespace

您必须在以下 cluster /节点上完成此考题:
Cluster Master 节点 工作节点
KSCH00301 ksch00301-master ksch00301-worker1

您可以使用以下命今来切换 cluster / 配置环境:
[candidate@cli] $ kubectl config use-context KSCHO0301

Context
您组织的安全策略包括:

  • ServiceAccount 不得自动挂载API 凭据
  • ServiceAccount 名称必须以“-sa”结尾

清单文件 /home/candidate/KSCHO0301/pod-manifest.yaml中指定的 Pod由于 ServiceAccount 指定错误而无法调度。

请完成以下项目:

Task
在现有 namespace dev 中创建一个名为 database-sa 的新ServiceAccount 确保此 ServiceAccount 自动挂载 API 凭据

使用 /home/candidate/KSCH00301/pod-manifest.yaml 中的清单文件来创建一个Pod。


最后,清理 namespace dev中任何未使用的 ServiceAccount。

题目操作:

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


kubectl apply -f dev-ns.yaml
kubectl get sa -n dev


2 创建 Pod 使用该 ServiceAccount
vi /home/candidate/KSCH00301/pod-manifest.yaml修改如下内容
……
metadata:
  name: backend
  namespace: dev #注意命名空间是否对
spec:
  serviceAccountName: backend-sa # 没有则添加一行,有则修改这一行为刚才创建的 ServiceAccount(考试时,默认已有这一行,需要修改。)
  containers:
……

kubectl apply -f /home/candidate/KSCH00301/pod-manifest.yaml
kubectl get pod -n dev


3. 删除没有使用的 ServiceAccount
查看所有 sa
kubectl get sa -n dev
查看已经在用的 sa
kubectl get pod -n dev -o yaml | grep -i serviceAccountName
删除不用的 sa
kubectl delete sa test01 -n dev
6.日志审计 log audit

环境准备:

mkdir /etc/kubernetes/logpolicy -p
cat << EOF >> /etc/kubernetes/logpolicy/audit-policy.yaml
apiVersion: audit.k8s.io/v1 # 这是必填项。
kind: Policy
# 不要在 RequestReceived 阶段为任何请求生成审计事件。
omitStages:
  - "RequestReceived"
rules:
  # 在日志中用 RequestResponse 级别记录 Pod 变化。
  - level: RequestResponse
    resources:
    - group: ""
      # 资源 "pods" 不匹配对任何 Pod 子资源的请求,
      # 这与 RBAC 策略一致。
      resources: ["pods"]
  # 在日志中按 Metadata 级别记录 "pods/log"、"pods/status" 请求
  - level: Metadata
    resources:
    - group: ""
      resources: ["pods/log", "pods/status"]

  # 不要在日志中记录对名为 "controller-leader" 的 configmap 的请求。
  - level: None
    resources:
    - group: ""
      resources: ["configmaps"]
      resourceNames: ["controller-leader"]

  # 不要在日志中记录由 "system:kube-proxy" 发出的对端点或服务的监测请求。
  - level: None
    users: ["system:kube-proxy"]
    verbs: ["watch"]
    resources:
    - group: "" # core API 组
      resources: ["endpoints", "services"]

  # 不要在日志中记录对某些非资源 URL 路径的已认证请求。
  - level: None
    userGroups: ["system:authenticated"]
    nonResourceURLs:
    - "/api*" # 通配符匹配。
    - "/version"

  # 在日志中记录 kube-system 中 configmap 变更的请求消息体。
  - level: Request
    resources:
    - group: "" # core API 组
      resources: ["configmaps"]
    # 这个规则仅适用于 "kube-system" 名字空间中的资源。
    # 空字符串 "" 可用于选择非名字空间作用域的资源。
    namespaces: ["kube-system"]

  # 在日志中用 Metadata 级别记录所有其他名字空间中的 configmap 和 secret 变更。
  - level: Metadata
    resources:
    - group: "" # core API 组
      resources: ["secrets", "configmaps"]

  # 在日志中以 Request 级别记录所有其他 core 和 extensions 组中的资源操作。
  - level: Request
    resources:
    - group: "" # core API 组
    - group: "extensions" # 不应包括在内的组版本。

  # 一个抓取所有的规则,将在日志中以 Metadata 级别记录所有其他请求。
  - level: Metadata
    # 符合此规则的 watch 等长时间运行的请求将不会
    # 在 RequestReceived 阶段生成审计事件。
    omitStages:
      - "RequestReceived"
EOF

参考文档:

您必须在以下 cluster /节点上完成此考题
Cluster Master 节点 工作节点
KSRS00602 ksrs00602-master ksrs00602-worker1

您可以使用以下命今来切换 cluster /配置环境:
[candidate@cli] $ kubectl config use-context KSRS00602

Task
在 cluster 中启用审计日志。为此,请启用日志后端,并确保:

  • 日志存储在 /var/log/kubernetes/logs.txt
  • 日志文件能保留 10
  • 最多保留 1个日审计日志文件

/etc/kubernetes/logpolicy/audit-policy.yaml 提供了基本策略。
它仅指定不记录的内容。

==基本策略位于 cluster的 master 节点上==

编辑和扩展基本策略以记录:

  • RequestResponse 级别的 cronjobs 更改
  • namespace frontwebdeployments 更改的请求体
  • Metadata 级别的所有 namespace 中的 ConfigMap 和 Secret 的更改

此外,添加一个全方位的规则以在 Metadata 级别记录所有其他请求

==不要忘记应用修改后的策略==

答题步骤:

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

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

#参考官方网址内容
……rules:
# namespaces changes at RequestResponse level
- level: RequestResponse
    resources:
    - group: ""
        resources: ["cronjobs"] #根据题目要求修改,比如题目要求的是 namespaces或者persistentvolumes。
#the request body of persistentvolumes/pods changes in the namespace front-apps
- level: Request
    resources:
    - group: ""
        resources: ["deployments"] #根据题目要求修改,比如题目要求的是 configmaps 或者 persistentvolumes 或者 pods。
    namespaces: ["frontweb"]
# 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 backup
cp /etc/kubernetes/manifests/kube-apiserver.yaml backup/
vi /etc/kubernetes/manifest
# 添加以下参数,注意空格要对齐,注意检查,如果考试中已经存在了则不要重复添加。
  - command:
    - --audit-policy-file=/etc/kubernetes/logpolicy/audit-policy.yaml #定义审计策略yaml文件位置,通过 hostpath 挂载
    - --audit-log-path=/var/log/kubernetes/logs.txt                   #定义审计日志位置,通过 hostpath 挂载
    - --audit-log-maxage=10                                           #定义保留旧审计日志文件的最大天数为 10 天
    - --audit-log-maxbackup=1                                         #定义要保留的审计日志文件的最大数量为 1 个


    volumeMounts:               #找到这个字段,添加下面内容
    - mountPath: /etc/kubernetes/logpolicy/audit-policy.yaml    #这里也可以写到目录/etc/kubernetes/logpolicy/
      name: audit
      readOnly: true    #这个为 true
    - mountPath: /var/log/kubernetes/
      name: audit-logs
      readOnly: false   #这个为 false

  volumes:                  #找到这个字段,添加下面内容
  - hostPath:
      path: /etc/kubernetes/logpolicy/audit-policy.yaml
      type: File            #file如果写到目录/etc/kubernetes/logpolicy/,则type:应为 type: DirectoryOrCreate
    name: audit
  - hostPath:
      path: /var/log/kubernetes/
      type: DirectoryOrCreate
    name: audit-logs

#4 重启 kubelet 服务
systemctl restart kubelet

等待 2 分钟后,再检查
kubectl get pod -A
tail /var/log/kubernetes/logs.txt

# 退出 root,退回到 candidate@master01
exit
# 退出 master01,退回到 candidate@node01
exit
7.AppArmor(限制容器对资源的访问)

环境准备:

cat << EOF >>/etc/apparmor.d/nginx_apparmor
#include <tunables/global>
nginx-profile-3  
profile nginx-profile-3 flags=(attach_disconnected) {
  #include <abstractions/base>

  file,

  # 拒绝所有文件写入
  deny /** w,
}
EOF

mkdir /home/candidate/KSSH00401 -pv
cat << EOF >> /home/candidate/KSSH00401/nginx-ds.yaml
apiVersion: v1
kind: Pod
metadata:
  name: podx
spec:
  containers:
  - image: busybox
    imagePullPolicy: IfNotPresent
    name: podx 
    command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
    resources: {}
  nodeName: node01
  dnsPolicy: ClusterFirst
  restartPolicy: Always
status: {}
EOF

参考资料:

Quick Reference
文档 AppArmorPodNode

您必须在以下 cluster /节点上完成此考题:
Cluster Master 节点 工作节点
KSSH00401 kssh00401-master kssh00401-worker1

您可以使用以下命令来切换 cluster /配置环境:
[candidate@cli] $ kubectl config use-context KSSHO0401

Context
AppArmor 已在 cluster 的工作节点上被启用。一个AppArmor 配置文件已存在,但尚未被实施。

==您可以使用浏览器打开一个额外的标签页来访问 AppArmor 的文档==

Task
在cluster 的工作节点上,实施位于 /etc/apparmor.d/nginx_apparmor 的现有AppArmor 配置文件

编辑位于 /home/candidate/KSSH00401/nginx-ds.yaml 的现有清单文件以应用AppArmor 配置文件。

最后,应用清单文件并创建其中指定的 Pod。

答题步骤:

1 切换到 node02 的 root 下
ssh node02
sudo -i

2 切换到 apparmor 的目录,并检查配置文件
cd /etc/apparmor.d/
#在考试时,可以先 cat /etc/apparmor.d/nginx_apparmor,有错误则改,没错误,则不要再改了
cat /etc/apparmor.d/nginx_apparmor
#include <tunables/global>

# nginx-profile-3 #注释掉 模拟环境里多写了一行的,会导致 apparmor_parser -q 的时候会报错。

profile nginx-profile-3 flags=(attach_disconnected) { 
#这句是正确的配置,不要修改。profile 后面的 nginx-profile-3 为 apparmor 策略模块的名字。

  file,

  # 拒绝所有文件写入
  deny /** w,
}


3 执行 apparmor 策略模块
#没有 grep 到,说明没有启动。
apparmor_status | grep nginx-profile-3
#加载启用这个配置文件
apparmor_parser -q /etc/apparmor.d/nginx_apparmor
# 再次检查有结果了
root@cka-master1:~# apparmor_status | grep nginx
   nginx-profile-3


4 修改 pod 文件
vi /home/candidate/KSSH00401/nginx-ds.yaml
#修改如下内容
……
metadata:
  name: podx
  annotations:
    container.apparmor.security.beta.kubernetes.io/podx: localhost/nginx-profile-3
    #添加 annotations,kubernetes.io/podx 名字和 containers 下的名字一样即可,nginx-profile-3 为前面在 worker node01 上执行的 apparmor 策略模块的名字。
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
8.Trivy 扫描镜像安全漏洞

环境准备:

https://github.com/aquasecurity/trivy
wget https://github.com/aquasecurity/trivy/releases/download/v0.48.2/trivy_0.48.2_Linux-64bit.tar.gz
tar -zxf trivy_0.48.2_Linux-64bit.tar.gz
mv trivy /usr/local/bin/

kubectl create namespace naboo

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: tri222
  namespace: naboo
spec: 
  containers:
  - name: amazonlinux
    image: amazonlinux:1
  - name: nginx
    image: nginx:1.19
EOF
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: tri333
  namespace: naboo
spec: 
  containers:
  - name: amazonlinux
    image: amazonlinux:2
  - name: vicuu-nginx
    image: vicuu/nginx:host
EOF

参考资料:

Quick Reference
文档 Trivy

您必须在以下 cluster /节点上完成此考题
Cluster Master 节点 工作节点
KSSC00401 kssc00401-master kssc00401-worker1

您可以使用以下命今来切换 cluster /配置环境
[candidate@cli] $ kubectl config use-context KSSCO0401

==您可以使用浏览器打开一个额外的标签页来访问 Trivy 的文档==

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

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

==Trivy 预装在 cluster 的 master 节点上; 它在原本的系统或工作节点上不可用。您必须连接到 cluster 的 master 节点才能使用 Trivy。==

答题步骤:

注意:这个题非常耗费时间,考试时关注一下剩余时间。如果时间剩余不多,可以放到最后做这道题。
方法 1:(推荐,能快一些)
1 切换到 Master 的 candidate 下
ssh master01

2 获取命名空间 naboo 下的所有 pod 的 image
kubectl get pods --namespace naboo --output=custom-columns="NAME:.metadata.name,IMAGE:.spec.containers[*].image"

3 检查镜像是否有高危和严重的漏洞
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。
#另外,网友 WilliamLee 还提供了一种方法,对 shell 命令比较熟习的,可以参考。
#让它后台扫,然后退出来继续做其他的,做完其他的回来看报告,删 pod。
#注意别忘了每道题要切换集群。


方法 2:(太消耗时间,因为考试时,有 5 个 pod,而且每一个 pod 里面还有两三个 image)
# 切换到 Master 的 root 下
ssh master01
#检查所有 pod
kubectl get pod -n naboo
#获取每一个 pod 的 image
kubect get pod XXXX -n naboo -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'
# 删除有问题的 pod
kubectl delete pod XXXX -n naboo
# 退出 master01,退回到 candidate@node01
exit
#请注意,考试时有 5 个 pod,每个 pod 里有多个 image 镜像。检查出有漏洞的镜像,则删除有这个镜像的 pod。


方法 3:(写 while 脚本有点麻烦)
(对于 pod 数量多的情况,可以使用下面方法)
# 切换到 Master 的 root 下
ssh master01
检查所有 pod
kubectl get po -n naboo
kubectl get po -n naboo | grep -v "NAME" | awk '{print $1}' > podlist.txt
cat podlist.txt
#循环检查 pod 里的 image
while read line;do
echo $line
kubectl get pod -n naboo $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
9.容器安全,更改特权 Pod

准备环境:

mkdir /home/candidate/finer-sunbeam/ -pv
kubectl create namespace lamp
cat << EOF > /home/candidate/finer-sunbeam/lamp-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: lamp-deployment
  namespace: lamp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: lamp
  template:
    metadata:
      labels:
        app: lamp
    spec:
      containers:
      - name: lamp-container
        image: nginx
        securityContext:
          readOnlyRootFilesystem: false
          allowPrivilegeEscalation: true
EOF
kubectl apply -f /home/candidate/finer-sunbeam/lamp-deployment.yaml
Quick Reference
文档 DeploymentPodNamespace

您必须在以下 cluster /节点上完成此考题:
Cluster 控制平面节点 工作节点
KSRS00502 ksrs00502-master ksrs00502-worker1

您可以使用以下命令来切换 cluster /配置环境:
[candidate@cli] $ kubectl config use-context KSRS00502

Context
必须更新一个现有的Pod 以确保其容器 的不变性

Task
修改运行在namespace lamp,名为 lamp-deployment 的现有 Deployment使其容器 :

  • 使用用户ID 10000 运行
  • 使用一个只读的根文件系统
  • 禁止特权提升

👉您可以在 /home/candidate/finer-sunbeam/lamp-deployment.yaml 找到lamp-deployment 的清单文件

答题步骤:


apiVersion: apps/v1
kind: Deployment
metadata:
  name: lamp-deployment
  namespace: lamp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: lamp
  template:
    metadata:
      labels:
        app: lamp
    spec:
      securityContext:
        runAsUser: 10000
      containers:
      - name: lamp-container
        image: nginx
        securityContext:
          readOnlyRootFilesystem: true
          allowPrivilegeEscalation: false



10.默认网络策略
Quick Reference
文档 NetworkPolicyPodNamespace

您必须在以下 cluster /节点上完成此考题:
Cluster Master 节点 工作节点
KSCS00101 kscs00101-master kscs00101-worker1

您可以使用以下命今来切换 cluster /配置环境
[candidate@cli] $ kubectl config use-context KSCS00101

Context
一个默认拒绝 (default-deny) 的 NetworkPolicy 可避免在未定义任何其他NetworkPolicy的namespace 中意外公开 Pod。

Task
为所有类型为 Ingress + Egress 的流量在 namespace development 中创建一个名为 denypolicy 的新默认拒绝 NetworkPolicy。

此新的 NetworkPolicy 必须拒绝 namespace development 中的所有Ingress + Egress 流量
将新创建的默认拒绝 NetworkPolicy 应用于在 namespace development 中运行的所有 Pod 。

==你可以在 /home/candidate/KSCS00101/network-policy.yaml 找到一个模板清单文件。==

准备环境:

mkdir -pv /home/candidate/KSCS00101
vim /home/candidate/KSCS00101/network-policy.yaml
kubectl create namespace development

考题操作:

#创建名为 denypolicy 的 NetworkPolicy,拒绝 testing 命名空间内所有 Ingress + Egress 流量
#(这里可能是 ingress 或 egress 或 ingress+egress,根据题目要求写。)
vi /home/candidate/KSCS00101/network-policy.yaml
#修改为
……
metadata:
name: denypolicy #修改 name
namespace: development #注意添加 namespace
spec:
podSelector: {}
policyTypes:
- Ingress #注意看题,是 Ingress + Egress(入口+出口),还是只是 Ingress 或只是 Egress。
- Egress #在 1.23 的考试中,只要求拒绝所有 Egress 流量,那就只写这这个- Egress 即可,这种情况就不要写- Ingress 了。

#创建
kubectl apply -f /home/candidate/KSCS00101/network-policy.yaml
#检查
kubectl describe networkpolicy denypolicy -n testing
11.启用 API server 认证

环境准备:

参考资料:

Quick Reference
文档 kubeadmClusterRoleBindingkubect

您必须在以下 cluster /节点上完成此考题
Cluster Master 节点 工作节点
KSCH00101 ksch00101-master ksch00101-worker1

您可以使用以下命今来切换 cluster /配置环境
[candidate@cli] $ kubectl config use-context KSCH00101

Context
kubeadm创建的集群的 Kubernetes API 服务器,出于测试目的,临时配置为允许未经身份验证和未经授权的访问,授予匿名用户 cluster-admin 的访问权限。

Task
重新配置 cluster的 Kubernetes API 服务器以确保只允许经过身份验证和授又的 REST 请求

使用授权模式 Node,RBAC 和准入控制器 NodeRestriction.

删除用户 system:anonymous 的 ClusterRoleBinding 来进行清理

==所有kubectl配置环境/文件也被配置为使用未经身份验证和未经授权的访问。==
==您不必更改它,但请注意,一旦完成 cluster 的安全加固,kubectl的配置将无法工作。==

==您可以使用位于 cluster 的 master 节点上, cluster 原本的kubectl 配置文件 /etc/kubernetes/admin.conf,以确保经过身份验证和授权的请求仍然被允许==

答题步骤:

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

请先执行如下命令,模拟这道题的初始环境。
脚本在 master01 的/root 目录下。
sh b.sh

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
# 退出 root,退回到 candidate@master01
exit
# 退出 master01,退回到 candidate@node01
exit
12.RBAC - RoleBinding

环境准备:

kubectl create ns db
kubectl -n db create serviceAccount test-sa-3
kubectl -n db create role role-1
kubectl -n db create role role-1 --verb=get,list,watch --resource='*'
kubectl -n db create rolebinding role-1-binding --role='role-1' --serviceaccount='db:test-sa-3'

cat << EOF > /opt/pod1.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: web-pod
  namespace: db
spec:
  serviceAccountName: test-sa-3
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: web-pod
EOF
    
kubectl apply -f /opt/pod1.yaml 
Quick Reference
文档 RoleRoleBindingServiceAccountPod

您必须在以下 cluster /节点上完成此考题:
Cluster Master 节点 工作节点
KSCH00201 ksch00201-master ksch00201-worker1

您可以使用以下命令来切换 cluster /配置环境
candidate@cli] $ kubectl config use-context KSCHO0201

Context
绑定到 Pod 的 ServiceAccount的 Role 授予过度宽松的权限。完成以下项目以减少权限集

Task
一个名为 web-pod 的现有 Pod 已在namespace db中运行

编辑绑定到 Pod 的 ServiceAccount test-sa-3 的现有 Role,允许endpoints类型的资源执行 watch 操作。

在namespace db 中创建一个名为 role-2,并允许namespaces 类型的资源 执行 update 操作的新 Role。

创建一个名为 role-2-binding 的新 RoleBinding,将新创建的 Role 绑定到 Pod 的 ServiceAccount 。

==请勿删除现有的 RoleBinding==

答题步骤:

#查看 ServiceAccount test-sa-3 对应的 rolebindings role-1-binding
#查看 rolebindings role-1-binding 对应的 role 为 role-1
root@cka-master01:~# kubectl describe rolebindings -n db
Name:         role-1-binding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  `Name:  role-1`
Subjects:
  Kind            Name                 Namespace
  ----            ----                 ---------
  `ServiceAccount  test-sa-3            db`


#编辑 role-1 权限:
kubectl edit role role-1 -n db
#修改如下内容
……
  resourceVersion: "30867"
  uid: 22e3c185-f7f5-4542-b86a-6ce153aa1c5a
rules: #模拟环境里要删除掉 null,然后添加以下内容。考试时,要根据实际情况修改。
- apiGroups: [""]
  resources: ["endpoints"] #只允许对 endpoints 资源类型执行 watch 操作。还有可能会考只允许对 services 资源 list 的操作
  verbs: ["watch"]  # 三种权限watch,get,list

#检查
root@cka-master01:~# kubectl describe role -n db role-1
Name:         role-1
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
 `endpoints  []                 []              [watch]`


#在 db 命名空间, 创建名为 role-2 的 role,并且通过 rolebinding 绑定 test-sa-3,只允许对 namespaces 做 delete 操作。
#记住 --verb 是权限,可能考 delete 或者 update 等 --resource 是对象,可能考 namespaces 或者 persistentvolumeclaims 等。
kubectl create role role-2 --verb=update --resource=namespaces -n db
kubectl create rolebinding role-2-binding --role=role-2 --serviceaccount=db:test-sa-3 -n db

#检查
root@cka-master01:~# kubectl describe rolebindings -n db role-2-binding
Name:         role-2-binding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
 `Name:  role-2`
Subjects:
  Kind            Name       Namespace
  ----            ----       ---------
 `ServiceAccount  test-sa-3  db`

13.第14题 TLS通信加强【新题】
Quick Reference
文档 cipher suites

您必须在以下 cluster /节点上完成此考题!
Cluster Master 节点 工作节点
KSMV00401 ksmv00401-master ksmv00401-worker1

您可以使用以下命今来切换 cluster / 配置环境
[candidate@cli] $ kubectl config use-context KSMV00401

Context
个现有的 Kubernetes 集群应通过更新其中一部分组件的 TLS 配置来进行加固。

Task
修改API 服务器和 etcd 之间通信的 TLS 配置

对于API服务器,删除对除 TLS 1.2 及更高版本之外的所有 TLS 版本的支持。此外,删除对除 TLS_ECDHE_ECDSA_WITH AES_128_GCM_SHA256 之外的所有密码套件 的支持

==确保应用配置的更改==

对于etcd,删除对除 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 之外的所有密码套件的支持。

==确保应用配置的更改。==

答题步骤:

# 修改kube-apiserver.yaml, vim /etc/kubernetes/manifests/kube-apiserver.yaml,删除如下两行,
    - --tls-min-version=VersionTLS13
    - --tls-cipher-suites=TLS_AES_128_GCM_SHA256
    
# 修改etcd.yaml, vim /etc/kubernetes/manifests/etcd.yaml,参考etcd命令帮助,删除如下一行, 
    - --cipher-suites=TLS_AES_128_GCM_SHA256
14.Sysdig & falco

环境准备:

node:
curl -s https://s3.amazonaws.com/download.draios.com/stable/install-sysdig | sudo bash
mkdir /opt/KSR00101/incidents/ -pv

master:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: tomcat
spec: 
  containers:
  - name: tomcat
    image: tomcat:7.0.59
EOF

Quick Reference
文档 FalcoDeploymentPodkubectl

您必须在以下 cluster /节点上完成此考题:
Cluster Master 节点 工作节点
KSRS00101 ksrs00101-master ksrs00101-worker1

您可以使用以下命令来切换 cluster /配置环境
[candidate@cli] $ kubectl config use-context KSRS00101

==您可以使用浏览器打开一个额外的标签页来访问 Falco 的文档。==

Task
使用运行时检测工具检测在属于 Pod tomcat 的单个容器中频繁产生和执行的异常进程。

cluster 的工作节点上已预装了两个工具:

  • sysdig
  • falco

使用您选择的工具(包括任何非预安装的工具),分析容器的行为至少 120秒,使用过滤器检测新生成和执行的进程。

==没有预安装的工具是被刻意配置成可以检测上述定义的异常进程的。==

在 /opt/KSRS00101/incidents/summary中存储一个事件文件,其中包含检测到的事件,每行一个,格式如下:

timestamp,uid or username,processName

以下示例显示了格式正确的事件文件

01:40:19.601363716,root,init
01:40:20.606013716,nobody,bash
01:40:21.137163716,1000,tar

==保持工具原本的时间戳格式==

==确保将事件文件存储在 cluster 的工作节点上。==

答题步骤:

#网友的反馈,之前的考试环境的 K8S 集群使用的容器全是 docker,新考试环境,部分使用 docker,部分使用 containerd。
#这也证明了 CKS 确实有多套考试环境的。
#所以此题给出了两个方法,方法 1 是 containerd 的,方法 2 是 docker 的。
#考试时,你可以先 docker ps 看一下,如果没有这个 pod,则应该是使用的 containerd。

考试形式 1 :K8S 集群使用 containerd
1 切换到 node02 的 root 下
ssh node02
sudo -i
2、先找到 containerd 的 socket
crictl info | grep sock
3、crontainerd 要使用 crictl 命令找到容器,题目要求的是 tomcat123,则 grep tomcat。
crictl ps | grep tomcat
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 120 -p "%evt.time,%user.uid,%proc.name" --cri /run/containerd/containerd.sock container.name=tomcat >> /opt/KSR00101/incidents/summary
sysdig -M 120 -p "%evt.time,%user.name,%proc.name" --cri /run/containerd/containerd.sock container.name=tomcat >> /opt/KSR00101/incidents/summary
#提示:如果考试时执行 sysdig 报错“Unable to load the driver”,则执行下面一条命令:(模拟环境里不需要执行)
#启用模块
sysdig-probe-loader
#然后再次执行 sysdig -M 30 ……
#如果还是报错,就重装一下 sysdig,命令为 apt install sysdig

#查看保存的文件
root@cka-node1:~# cat /opt/KSR00101/incidents/summary |head
11:25:21.238100288,root,java
11:25:21.238102819,root,java
11:25:21.238103334,root,java
11:25:21.238111198,root,java
11:25:21.238114193,root,java
11:25:21.288211283,root,java
11:25:21.288218106,root,java
11:25:21.288219427,root,java
11:25:21.288233586,root,java
11:25:21.288241225,root,java

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

考试形式 2 :K8S 集群使用 docker(1.24 基本不考这种了)
#以下命令记住即可,模拟环境使用的是 containerd。
1 切换到 node02 的 root 下
ssh node02
sudo -i
#首先找到容器的 container id:,我这里的容器 id 为 40c3c3e8b813
docker ps | grep tomcat
#通过 sysdig 扫描容器 30s 并输出到指定文件:
sysdig -h 和-l 查看帮助
#注:可以使用 sysdig -l |grep time 过滤,确认输出格式字段
sysdig -l | grep time
sysdig -l | grep uid
sysdig -l | grep proc

#开始扫描
sysdig -M 30 -p "%evt.time,%user.uid,%proc.name" container.id=40c3c3e8b813 > /opt/KSR00101/incidents/summary
#查看保存的文件
cat /opt/KSR00101/incidents/summary |head

# 退出 root,退回到 candidate@node02
exit
# 退出 node02,退回到 candidate@node01
exit
15. kube-bench 修复不安全项

您必须在以下 cluster /节点上完成此考题:
Cluster Master 节点 工作节点
KSCS00201 kscs00201-master kscs00201-worker1

您可以使用以下命今来切换 cluster /配置环境
[candidate@cli] $kubectl config use-context KSCS00201

Context
针对 kubeadm 创建的 cluster 运行 CIS 基准测试工具时,发现了多个必须立即解决的问题

Task
通过配置修复所有问题并重新启动受影响的组件以确保新设置生效。

修复针对 Kubelet 发现的所有以下违规行为:

2.1.2 Ensure that the --anonymous-auth argument is set to false                         FAIL
2.1.3 Ensure that the --authorization-mode argument is not set to AlwaysAllow           FAIL
翻译:
2.1.2确保anonymous-auth参数设置为false                     失败
2.1.3确保——authorization-mode参数没有设置为alwaysallow      失败

==尽可能使用 Webhook身份验证/授权==

修复针对 etcd 发现的所有以下违规行为:

2.2 Ensure that the --client-cert-auth argument is set to true                          FAIL
翻译:
2.2确保——client-cert-auth参数设置为true                    失败

环境配置:

wget https://github.com/aquasecurity/kube-bench/releases/download/v0.6.17/kube-bench_0.6.17_linux_amd64.deb
dpkg -i  kube-bench_0.6.17_linux_amd64.deb


root@cka-master1:~# sed -i 's/- --authorization-mode=Node,RBAC/#- --authorization-mode=Node,RBAC/g' /etc/kubernetes/manifests/kube-apiserver.yaml
root@cka-master1:~# cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -e "- --authorization-mode=Node,RBAC"
          #- --authorization-mode=Node,RBAC


做题操作:

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

sh a.sh

# 2 修改 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

# 3 修改 kubelet
kube-bench node

#修复方法 1:(推荐)
#如果考试时,你用方法 1 改完后, kubelet 启动不了, 肯定是你哪里改错了,如果又排查不出来, 则恢复此文件, 再使用方法 2 修改。
systemctl status kubelet
cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf 
#中你也会看到 Environment="KUBELET_CONFIG_ARGS=--config=/var/lib/kubelet/config.yaml"。
#所以去修改这个文件

#修改之前,备份一下配置文件。
mkdir bak1
cp /var/lib/kubelet/config.yaml bak1/
vim /var/lib/kubelet/config.yaml
# 修改
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous: #修改 anonymous 下的,将 true 改为 false
    enabled: false #改为 false
  webhook:
    cacheTTL: 0s
    enabled: true #这个 webhook 下的 true 不要改
  x509:
    clientCAFile: /etc/kubernetes/pki/ca.crt
authorization: #修改 authorization 下的
  mode: Webhook #改为 Webhook
    webhook:
……

#编辑完后重新加载配置文件,并重启 kubelet
systemctl daemon-reload
systemctl restart kubelet.service

修复方法 2:(不推荐, 建议用方法 1)
考试中,任选一种方法即可,模拟环境里推荐第一种方法。
systemctl status kubelet
修改之前,备份一下配置文件
mkdir bak1
cp /etc/systemd/system/kubelet.service.d/10-kubeadm.conf bak1/
vi /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
#在[Service]下面添加
Environment="KUBELET_SYSTEM_PODS_ARGS=--anonymous-auth=false"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook"
#在 ExecStart 后追加
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS
$KUBELET_SYSTEM_PODS_ARGS $KUBELET_AUTHZ_ARGS
#编辑完后重新加载配置文件,并重启 kubelet
systemctl daemon-reload
systemctl restart kubelet.service


# 4 修改 etcd
kube-bench

#修改之前,备份一下配置文件。
mkdir bak1
cp /etc/kubernetes/manifests/etcd.yaml bak1/
vim /etc/kubernetes/manifests/etcd.yaml
#修改
- --client-cert-auth=true #修改为 true

修改完成后,等待 2 分钟,再检查一下所有 pod,确保模拟环境里的所有 pod 都正常。
kubectl get pod -A

# 退出 root,退回到 candidate@master01
exit
# 退出 master01,退回到 candidate@node01
exit
做下一题之前,确保所有的 pod 都是 Running,特别是 kube-apiserver-master01 也正常。(考试时,也要确保这个 apiserver 是正常的)
模拟环境里, calico-apiserver 和 calico-system 的几个 pod 可能需要比较长的时间才能恢复到 Running 状态,此时只要确保其他 pod 已恢复 Running 就可以继续
做题了。
16.Dockerfile 检测

环境准备:

mkdir -pv /home/candidate/KSSC00301/
cat << EOF > /home/candidate/KSSC00301/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;"]
EOF

cat << EOF > /home/candidate/KSSC00301/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:
        run: couchdb
    spec:
      containers:
      - name: couchdb
        image: demo:v1
        imagePullPolicy: IfNotPresent
          livenessProbe:
            httpGet:
              path: /healthCheck
              port: 8080
        ports
        - name: http
          containerPort: 8080
          protocol: TCP
        volumeMounts:
        - name: database-storage
          mountPath: /var/lib/database
        securityContext:
          {"Capabilities": {'add': ['NET_BIND_SERVICE','SYS_ADMIN'], 'drop': ['all']}, 'privileged': False, 'readonlyRootFilesystem': False, 'runAsUser': 65535}
        resources:
          limits:
            cpu: 300m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 100Mi
EOF

参考资料:

您必须在以下 cluster /节点上完成此考题:
Cluster Master 节点 工作节点
KSSC00301 kssc00301-master kssc00301-worker1

您可以使用以下命令来切换 cluster /配置环境:
[candidate@cli] $ kubectl config use-context KSSCO0301

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


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

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

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

答题步骤:

注意,本次的 Dockerfile 和 deployment.yaml 仅修改即可,无需部署。
<1> 修改 Dockerfile

vi /home/candidate/KSSC00301/Dockerfile
1、仅将 CMD 上面的 USER root 修改为 USER nobody,不要改其他的 USER root。
USER nobody
2、修改基础镜像为题目要求的 ubuntu:22.04
FROM ubuntu:22.04
#修改后
FROM ubuntu:22.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 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 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;"]



<2> 修改 deployment.yaml
vi /home/candidate/KSSCO0301/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}
#修改后

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
    spec:
      containers:
      - name: couchdb
        image: demo:v1
        imagePullPolicy: IfNotPresent
          livenessProbe:
            httpGet:
              path: /healthCheck
              port: 8080
        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': False, 'runAsUser': 65535}
        resources:
          limits:
            cpu: 300m
            memory: 500Mi
          requests:
            cpu: 100m
            memory: 100Mi
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,478评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,825评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,482评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,726评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,633评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,018评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,168评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,320评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,264评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,288评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,995评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,587评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,909评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,284评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,862评论 2 339

推荐阅读更多精彩内容