使用kube-bench工具检查Kubernetes的硬化情况
首先
我开始学习有关Kubernetes安全性的内容,了解到了CIS基准测试。
这是由互联网安全中心发布的各种软件和平台的强化指南。
除了Kubernetes的CIS基准测试之外,还有其他各种操作系统的指南。
我总结了关于这些内容的确认结果。
截至2021年2月,可获得的Kubernetes CIS基准版本为v1.6.0(于2020年7月23日发布,适用于Kubernetes 1.16-1.18),PDF文件大约有270页,要全部阅读确实很困难。实际上,各个安全项目都以概述、配置确认方法、配置方法、影响、默认值、参考信息等形式进行总结,所以并不是很难理解。即使只看目录,也能了解概要,如果感兴趣的话,可以看一看。
作为一个重要的基准,它的主要构成如下。
-
- 控制平面组件
-
- etcd
-
- 控制平面配置
-
- 工作节点
- 策略
为了逐个确认这些事项,需要相当大的工作量,但是有一个名为 kube-bench 的工具可以自动检查。
运行 kube-bench 可以根据 CIS Kubernetes Benchmark 来确认各种配置的情况。
本文将尝试使用 kube-bench 检查在没有考虑安全性的情况下创建的家庭 Kubernetes 环境。(请注意,仅仅是运行工具并不包含结果的安全增强方法。没做最重要的一步… 我们计划逐步学习并进行相应改进。)
在 kube-bench 的 Readme.md 中,列举了一些注意事项:
– kube-bench 的检查内容并不完全对应 CIS 基准测试
– 无法对 Kubernetes 托管服务(如 GKE)的控制平面进行检查。
虽然有点离题,但据看起来各个云服务提供商都在对托管服务中的“托管”部分进行安全检查,所以通常情况下我们不需要特别关注这个问题。
另外,关于公开了CIS基准的各个云服务提供商,有许多项目被判定为“不合格”,但我们必须意识到“不合格”并不意味着完全不可行。这可能是因为所设想的架构不同等原因导致的。
有些云平台并不进行CIS基准评估。例如,关于Amazon EKS,在2020年7月11日的博客中提到了以下内容。(但是,kube-bench有针对EKS的模块可用)。
中国国家互联网安全中心(CIS)Kubernetes基准提供了良好的实践指南,用于自管理的Kubernetes集群的安全设置。然而,它无法准确评估由Amazon EKS运行的AWS托管Kubernetes集群的安全设置状态。
我会在“参考”部分列出其他各种托管云的CIS基准测试结果。
环境
好吧,暂且不谈托管服务的事情,家里的Kubernetes环境的配置如下。
在家里的Kubernetes环境中,我们在笔记本电脑上安装了CentOS并准备了KVM环境,然后在其上配置了Kubernetes的各个节点作为虚拟机。
-
- KVM ホスト
CentOS Linux release 8.2.2004 (Core)
Master / Node ( 1 Master / 3 Worker 構成 )
Ubuntu 20.04.1 LTS
containerd 1.4.3-1
calico 3.11
kubernetes 1.20.1
此外,由于家庭局域网上的 Kubernetes 集群仅用于学习目的,因此未考虑安全性问题。控制器和节点均处于默认安全状态。
在構建 Kubernetes 集群方面,我們使用了 kubernetes docs 中 kubeadm 使用模式,並且使用 Containerd 作為容器使用的工具。
(※ 根據 CIS Kubernetes Benchmark,似乎並未檢查到容器部分)
根據 CIS 基準,似乎僅適用於 Kubernetes 1.18 以前的版本,但我們認為在這個環境下也可以應用許多部分,因此會試著確認一下。
应用kube-bench
在 kube-bench 的 Readme.md 文件中,介绍了以下4种导入方法。
-
- コンテナ内から実行
-
- kube-bench インストールコンテナを実行しホストにインストール
-
- バイナリ、コンフィグ、テスト関連ファイルをダウンロード
- ソースからのコンパイル
我想尝试一下看起来最简便的方法,即“从容器内部执行”。
(实际上,我在Kubernetes上以Pod的形式运行。)
从容器中运行 kube-bench 的概述
根据 Readme.md 中的 “Running in a kubernetes cluster” 部分的指示,执行 job.yaml 文件。
根据我的理解,当在 Redame.md 中运行 job.yaml 文件时,可以看到会对主节点和工作节点进行检查,但在我们的环境中,只有节点验证被执行了。虽然我们可以使用 job-node.yaml 和 job-master.yaml 进行节点和主节点的检查,但实际上只能检查到以下部分:1. 控制平面组件,4. 工作节点,5. 策略。对于无法检查到 etcd 和控制平面配置的原因,我进行了多次尝试。最终的结论是,通过基于 master 用的 job-master.yaml 文件并指定 kube-bench –version=1.18,我们可以检查到所有项目(修订内容如下)。在使用 kube-bench 时,如果不指定 –version 选项,则会自动判断版本,但我认为在 kubernetes 1.20 上无法正确判断(原本仅适用于 1.16 – 1.18 版本)。
在 YAML 中,大致上有以下配置项被设定。(对于master和node两种用途,配置有所不同。以下是master的示例)
-
- kubernetes の job として Pod を実行
-
- job.spec.template.spec.hostPID を true に設定することにより、コンテナホストと PID namespace を共有する (それにより、ホスト上のプロセスの詳細(ptrace)を確認することができるようになる)
-
- nodeSelector で実行対象ノードを選択する
-
- toleration を用いて master ノードでも稼働できるようにする
-
- aquasec/kube-bench:latest イメージを利用する
-
- command に kube-bench を指定 (引数に node/master を指定する)
- コンテナホスト上の kubernetes 関連ファイルのパスを hostPath でコンテナ内に ReadOnly でマウントし、確認できるようにする
由于环境(Kubernetes v1.20.1)已经超出kube-bench的支持版本范围,因此进行了kube-bench的版本指定(1.18)。修正细节如下所示(请参考#后面的注释部分)。
---
apiVersion: batch/v1
kind: Job
metadata:
name: kube-bench-master
spec:
template:
spec:
hostPID: true
nodeSelector:
node-role.kubernetes.io/master: ""
tolerations:
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: kube-bench
image: aquasec/kube-bench:latest
# command: ["kube-bench", "master"] # 元の command 部分をコメントアウト
command: ["kube-bench"] # command は kube-bench のみに変更
args: ["--version=1.18"] # 引数に --version=1.18 を追加
volumeMounts:
…略
kube-bench执行示例
执行起来并不难,只需要应用yaml文件。
将会创建一个作业(job)并在Pod中执行处理。(*下面的job.yaml文件是在上述部分基于job-master.yaml进行修改的文件。)
# kubectl apply -f job.yaml
job.batch/kube-bench-master created
# kubectl get jobs -o wide
NAME COMPLETIONS DURATION AGE CONTAINERS IMAGES SELECTOR
kube-bench-master 1/1 4s 5s kube-bench aquasec/kube-bench:latest controller-uid=fe19f9fe-e752-487f-bf5f-fe7f2b42d7c4
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-bench-master-zr44r 0/1 Completed 0 9s 10.200.163.35 k8sctl0 <none> <none>
需要注意的是执行节点。
在上面的例子中,它是在 k8sctl0 上执行的。(由于只有一个控制平面,所以当然是这样)
如果有多个节点,则取决于 kube-scheduler 的选择来确定在哪个节点上执行。
如果你认为已经修改了特定节点的设置但检查结果没有变成 [PASS],那可能是被分配给了其他节点进行检查。是的,我自己有过这样的经历。
您可以在 Pod 的日志中查看执行结果。
# kubectl logs kube-bench-master-zr44r
[INFO] 1 Master Node Security Configuration
[INFO] 1.1 Master Node Configuration Files
[PASS] 1.1.1 Ensure that the API server pod specification file permissions are set to 644 or more restrictive (Automated)
...
[WARN] 1.1.9 Ensure that the Container Network Interface file permissions are set to 644 or more restrictive (Manual)
[WARN] 1.1.10 Ensure that the Container Network Interface file ownership is set to root:root (Manual)
[PASS] 1.1.11 Ensure that the etcd data directory permissions are set to 700 or more restrictive (Automated)
[FAIL] 1.1.12 Ensure that the etcd data directory ownership is set to etcd:etcd (Automated)
[PASS] 1.1.13 Ensure that the admin.conf file permissions are set to 644 or more restrictive (Automated)
...
1.1.12 On the etcd server node, get the etcd data directory, passed as an argument --data-dir,
from the below command:
ps -ef | grep etcd
Run the below command (based on the etcd data directory found above).
For example, chown etcd:etcd /var/lib/etcd
...
== Summary master ==
45 checks PASS
10 checks FAIL
10 checks WARN
0 checks INFO
== Summary total ==
45 checks PASS
10 checks FAIL
10 checks WARN
0 checks INFO
对于每个部分的项目,将会显示[PASS]、[WARN]、[FAIL]。
尽管示例中没有提及,但已对1至5个部分进行了检查。
此外,对于被标记为“手动”的项目,如果能够确认则标记为[通过],否则标记为[警告],如果标记为[警告],则需要自行确认。
例如,在1.1.9版本中的CNI相关文件权限,我们的环境是使用Calico,在/etc/cni/net.d/目录下的文件权限比644更严格,但似乎无法读取。
作为注意事项,5.条款中包括了对 RBAC、Pod 安全策略、网络策略、密钥等的规定。
所有这些规定都要求将 RBAC 设定为最低必要权限。
由于这些内容不能自动识别,所以几乎全部都被标注为[警告]。
这意味着最终我们还是需要自行妥善管理。
对于[警告]和[失败]的案例,接下来会提供简单的解决方法。
在1.1.12的例子中,建议将etcd的–data-dir的所有者和组设置为etcd:etcd。
经过确认,发现所有者和组被设置为root。
# ps -ef | grep etcd | grep data-dir
root 1378 1313 1 00:48 ? 00:06:09 etcd --advertise-client-urls=https://192.168.199.200:2379 --cert-file=/etc/kubernetes/pki/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/etcd --initial-advertise-peer-urls=https://192.168.199.200:2380 --initial-cluster=k8sctl0=https://192.168.199.200:2380 --key-file=/etc/kubernetes/pki/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.199.200:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.199.200:2380 --name=k8sctl0 --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/etc/kubernetes/pki/etcd/peer.key --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt --snapshot-count=10000 --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
# ls -ld /var/lib/etcd
drwx------ 3 root root 4096 Feb 11 00:48 /var/lib/etcd
我认为该文中的应对方法相对易懂。
如果你对内容不理解或者想要了解更多详情,可以查看CIS Kubernetes基准的PDF文件中的相应部分,其中包含更详细的描述、确认方法以及相关参考信息的链接。
根据这些信息,通过进行硬化设置,可以增强安全性。
注意事项是,如果进行了相关的设置,无法保证其能够正确运行。
例如,在节点端进行检查时,会建议将–protect-kernel-defaults设置为true。
然而,如果采取了这样的措施,kubelet将无法运行,并且需要调整内核参数。
已经有人总结了这样的解决方案。
在设置kubelet的–protect-kernel-defaults为true时需要进行的内核调优。
需要调整内核参数以使kubelet的–protect-kernel-defaults参数为true。
我认为,仅仅按照指南简单设置并不意味着这就可以了。但是,有了硬化指南和工具,对应策略的复杂度将完全不同。
结束
由CIS编制的硬化指南以及基于该指南的诊断工具kube-bench的存在,我认为降低了Kubernetes的硬化难度。然而,需要记住的是,硬化只是增强安全性的手段之一,而不是只要进行硬化就可以了,因此在使用和运营中需要注意。
参考)■ 信息共享与安全中心
https://www.cisecurity.org/
■ kube-bench
https://github.com/aquasecurity/kube-bench
■ CIS 基准(GKE / anthos)
请访问以下链接查阅相关文件:
– GKE:https://cloud.google.com/kubernetes-engine/docs/concepts/cis-benchmarks?hl=ja
– Anthos:https://cloud.google.com/anthos/gke/docs/on-prem/1.5/concepts/cis-benchmarks?hl=ja
■ CIS基准测试(AKS)
https://docs.microsoft.com/zh-cn/azure/aks/security-hardened-vm-host-image
■ CIS基准(IKS)
https://cloud.ibm.com/docs/containers?topic=containers-cis-benchmark