在前面的章节中,我们研究了 Kubernetes 集群的架构。Kubernetes 集群由主组件(包括kube-apiserver
、etcd
、kube-scheduler
、CoreDNS、kube-controller-manager
和cloud-controller-manager
)和节点组件(包括kubelet
、kube-proxy
和container-runtime
组成。主组件负责集群管理。它们构成了集群的控制平面。另一方面,节点组件负责节点上的容器和容器的功能。
在 第 3 章威胁建模中,我们简要讨论了 Kubernetes 集群中的组件需要进行配置以确保集群的安全性。任何集群组件的泄露都可能导致数据泄露。环境配置不当是传统或微服务环境中数据泄露的主要原因之一。了解每个组件的配置以及每个设置如何打开新的攻击面非常重要。因此,集群管理员了解不同的配置非常重要。
在本章中,我们将详细介绍如何保护集群中的每个组件。在许多情况下,不可能遵循所有的安全最佳实践,但是如果攻击者试图利用易受攻击的配置,突出风险并制定缓解策略是很重要的。
对于每个主组件和节点组件,我们简要讨论 Kubernetes 集群中具有安全相关配置的组件的功能,并详细查看每个配置。我们查看这些配置的可能设置,并强调推荐的做法。最后,我们介绍kube-bench
并介绍如何使用它来评估集群的安全状况。
在本章中,我们将涵盖以下主题:
- 保护 kube-apiserver
- 保护 kubelet
- 固定 etcd
- 保护 kube 调度程序
- 保护 kube-控制器-管理器
- 保护 coreens
- 对集群的安全配置进行基准测试
kube-apiserver
是你集群的入口。它实现了一个表示状态转移 ( REST ) 应用编程接口 ( API )来授权和验证对对象的请求。它是在 Kubernetes 集群内通信和管理其他组件的中央网关。它执行三个主要功能:
- API 管理 :
kube-apiserver
公开用于集群管理的 API。开发者和集群管理员使用这些 API 来修改集群的状态。 - 请求处理:对对象管理和集群管理的请求进行验证和处理。
- 内部消息传递:API 服务器与集群中的其他组件进行交互,确保集群正常运行。
对应用编程接口服务器的请求在处理前要经过以下步骤:
- 认证 :
kube-apiserver
首先验证请求的来源。kube-apiserver
支持多种认证模式,包括客户端证书、承载令牌、超文本传输协议 ( HTTP )认证。 - 授权:一旦验证了起源的身份,API 服务器验证允许起源执行请求。
kube-apiserver
默认支持基于属性的访问控制 ( ABAC )、基于角色的访问控制 ( RBAC )、节点授权、网络钩子进行授权。RBAC 是推荐的授权方式。 - 准入控制器:一旦
kube-apiserver
认证并授权该请求,准入控制器解析该请求,以检查集群内是否允许该请求。如果该请求被任何接纳控制器拒绝,则该请求被丢弃。
kube-apiserver
是集群的大脑。API 服务器的泄露会导致集群泄露,因此 API 服务器的安全至关重要。Kubernetes 提供了无数的设置来配置 API 服务器。接下来让我们看看一些与安全相关的配置。
要保护应用编程接口服务器,您应该执行以下操作:
- 禁用匿名认证:使用
anonymous-auth=false
标志将匿名认证设置为false
。这确保了被所有身份验证模块拒绝的请求不会被视为匿名请求而被丢弃。 - 禁用基础认证:基础认证在
kube-apiserver
中为了方便支持,不宜使用。基本身份验证密码无限期保留。kube-apiserver
使用--basic-auth-file
参数启用基本身份验证。请确保不使用此参数。 - 禁用令牌身份验证 :
--token-auth-file
为您的集群启用基于令牌的身份验证。不建议使用基于令牌的身份验证。静态令牌永远存在,需要重启应用编程接口服务器才能更新。客户端证书应该用于身份验证。 - 使用 HTTPS 确保与库贝莱的连接:默认情况下,
--kubelet-https
设置为true
。确保该参数没有设置为kube-apiserver
的false
。 - 禁用分析:使用
--profiling
启用分析会暴露不必要的系统和程序细节。除非您遇到性能问题,否则通过设置--profiling=false
禁用性能分析。 - 禁用 alwaysacclave:
--enable-admission-plugins
可用于启用默认未启用的准入控制插件。AlwaysAdmit
接受请求。确保插件不在--enabled-admission-plugins
列表中。 - 使用 AlwaysPullImages :准入控制确保节点上的映像在没有正确凭证的情况下无法使用。这可以防止恶意 pods 为节点上已经存在的映像创建容器。
- 使用安全上下文拒绝:如果
PodSecurityPolicy
未启用,应使用该准入控制器。SecurityContextDeny
确保 Pod 不能修改SecurityContext
升级权限。 - 启用审核:审核默认在
kube-apiserver
中启用。确保--audit-log-path
设置为安全位置的文件。此外,确保审核的maxage
、maxsize
和maxbackup
参数设置符合合规性预期。 - 禁用 AlwaysAllow 授权:授权模式确保来自拥有正确权限的用户的请求被 API 服务器解析。不要将
AlwaysAllow
与--authorization-mode
一起使用。 - 启用 RBAC 授权 : RBAC 是 API 服务器推荐的授权模式。ABAC 很难使用和管理。RBAC 角色和角色绑定的易用性和易更新性使 RBAC 适合经常扩展的环境。
- 确保对 kubelet 的请求使用有效证书:默认情况下,
kube-apiserver
对kubelet
的请求使用 HTTPS。启用--kubelet-certificate-authority
、--kubelet-client-key
和--kubelet-client-key
可确保通信使用有效的 HTTPS 证书。 - 启用服务账户查找:除了确保服务账户令牌有效,
kube-apiserver
还应验证令牌存在于etcd
中。确保--service-account-lookup
未设置为false
。 - 启用 PodSecurityPolicy 策略 :
--enable-admission-plugins
可用于启用PodSecurityPolicy
。正如我们在第 5 章中看到的,配置 Kubernetes 安全边界PodSecurityPolicy
用于定义 pod 的安全敏感标准。我们将在 第 8 章中深入探讨如何创建 pod 安全策略来保护 Kubernetes pod。 ** 使用服务帐户密钥文件:使用--service-account-key-file
可以旋转服务帐户的密钥。如果未指定,则kube-apiserver
使用来自传输层安全性 ( TLS )证书的私钥来签署服务帐户令牌。* 启用授权请求 etcd :--etcd-certfile
和--etcd-keyfile
可用于识别对etcd
的请求。这确保了任何未识别的请求都可以被etcd
拒绝。* 不要禁用服务账户准入控制:该准入控制自动服务账户。启用ServiceAccount
确保具有受限权限的自定义ServiceAccount
可以用于不同的 Kubernetes 对象。* 不要使用自签名证书请求:如果kube-apiserver
启用了 HTTPS,则应提供一个--tls-cert-file
和一个--tls-private-key-file
,以确保不使用自签名证书。* 到 etcd 的安全连接:设置--etcd-cafile
允许kube-apiserver
使用证书文件通过安全套接字层 ( SSL )向etcd
验证自身。* 使用安全的 TLS 连接:仅将--tls-cipher-suites
设置为强密码。--tls-min-version
用于设置最低支持的 TLS 版本。TLS 1.2 是推荐的最低版本。* 启用高级审核:将--feature-gates
设置为AdvancedAuditing=false
可以禁用高级审核。确保该字段存在并设置为true
。高级审计有助于在发生违规时进行调查。*
*在 Minikube 上,kube-apiserver
配置如下:
$ps aux | grep kube-api
root 4016 6.1 17.2 495148 342896 ? Ssl 01:03 0:16 kube-apiserver --advertise-address=192.168.99.100 --allow-privileged=true --authorization-mode=Node,RBAC --client-ca-file=/var/lib/minikube/certs/ca.crt --enable-admission-plugins=NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,NodeRestriction,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota --enable-bootstrap-token-auth=true --etcd-cafile=/var/lib/minikube/certs/etcd/ca.crt --etcd-certfile=/var/lib/minikube/certs/apiserver-etcd-client.crt --etcd-keyfile=/var/lib/minikube/certs/apiserver-etcd-client.key --etcd-servers=https://127.0.0.1:2379 --insecure-port=0 --kubelet-client-certificate=/var/lib/minikube/certs/apiserver-kubelet-client.crt --kubelet-client-key=/var/lib/minikube/certs/apiserver-kubelet-client.key --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname --proxy-client-cert-file=/var/lib/minikube/certs/front-proxy-client.crt --proxy-client-key-file=/var/lib/minikube/certs/front-proxy-client.key --requestheader-allowed-names=front-proxy-client --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --requestheader-extra-headers-prefix=X-Remote-Extra- --requestheader-group-headers=X-Remote-Group --requestheader-username-headers=X-Remote-User --secure-port=8443 --service-account-key-file=/var/lib/minikube/certs/sa.pub --service-cluster-ip-range=10.96.0.0/12 --tls-cert-file=/var/lib/minikube/certs/apiserver.crt --tls-private-key-file=/var/lib/minikube/certs/apiserver.key
如您所见,默认情况下,在 Minikube 上,kube-apiserver
并没有遵循所有的安全最佳实践。例如:默认不启用PodSecurityPolicy
,默认不设置强密码套件和tls
最低版本。集群管理员有责任确保应用编程接口服务器配置安全。
kubelet
是 Kubernetes 的节点代理。它管理 Kubernetes 集群内对象的生命周期,确保对象在节点上处于健康状态。
要保护kubelet
,您应该执行以下操作:
- 禁用匿名身份验证:如果启用匿名身份验证,则被其他身份验证方法拒绝的请求将被视为匿名。确保为
kubelet
的每个实例设置--anonymous-auth=false
。 - 设置授权模式:使用配置文件设置
kubelet
的授权模式。使用--config
参数指定配置文件。确保授权模式列表中没有AlwaysAllow
。 - 旋转库伯莱证书 :
kubelet
证书可以使用kubelet
配置文件中的RotateCertificates
配置进行旋转。这应该与RotateKubeletServerCertificate
一起使用,以自动请求服务器证书的轮换。 - 提供证书颁发机构(CA)捆绑包:CA 捆绑包由
kubelet
用来验证客户端证书。这可以使用配置文件中的ClientCAFile
参数进行设置。 - 禁用只读端口:默认为
kubelet
启用只读端口,应该禁用。只读端口没有身份验证或授权。 - 启用节点限制准入控制器:准入控制器
NodeRestriction
只允许kubelet
修改其绑定到的节点上的节点和 pod 对象。 - 限制对库布雷应用编程接口的访问:只有
kube-apiserver
组件与kubelet
应用编程接口交互。如果尝试与节点上的kubelet
API 通信,则是禁止的。这是通过将 RBAC 用于kubelet
来保证的。
在 Minikube 上,kubelet
配置如下:
root 4286 2.6 4.6 1345544 92420 ? Ssl 01:03 0:18 /var/lib/minikube/binaries/v1.17.3/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=docker --fail-swap-on=false --hostname-override=minikube --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.99.100 --pod-manifest-path=/etc/kubernetes/manifests
与应用编程接口服务器类似,并非所有安全配置都默认用于kubelet
—例如,禁用只读端口。接下来,我们将讨论集群管理员如何保护etcd
。
etcd
是 Kubernetes 用于数据存储的键值存储。它存储 Kubernetes 集群的状态、配置和机密。只有kube-apiserver
可以访问etcd
。etcd
的妥协会导致集群妥协。
要保护etcd
,您应该执行以下操作:
- 限制节点访问:使用 Linux 防火墙,确保只允许需要访问
etcd
的节点访问。 - 确保 API 服务器使用 TLS:
--cert-file``--key-file
确保对etcd
的请求是安全的。 - 使用有效证书 :
--client-cert-auth
确保来自客户端的通信是使用有效证书进行的,将--auto-tls
设置为false
确保不使用自签名证书。 - 静态加密数据 :
--encryption-provider-config
传递给 API 服务器,确保数据在etcd
中静态加密。
在 Minikube 上,etcd
配置如下:
$ ps aux | grep etcd
root 3992 1.9 2.4 10612080 48680 ? Ssl 01:03 0:18 etcd --advertise-client-urls=https://192.168.99.100:2379 --cert-file=/var/lib/minikube/certs/etcd/server.crt --client-cert-auth=true --data-dir=/var/lib/minikube/etcd --initial-advertise-peer-urls=https://192.168.99.100:2380 --initial-cluster=minikube=https://192.168.99.100:2380 --key-file=/var/lib/minikube/certs/etcd/server.key --listen-client-urls=https://127.0.0.1:2379,https://192.168.99.100:2379 --listen-metrics-urls=http://127.0.0.1:2381 --listen-peer-urls=https://192.168.99.100:2380 --name=minikube --peer-cert-file=/var/lib/minikube/certs/etcd/peer.crt --peer-client-cert-auth=true --peer-key-file=/var/lib/minikube/certs/etcd/peer.key --peer-trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt --snapshot-count=10000 --trusted-ca-file=/var/lib/minikube/certs/etcd/ca.crt
etcd
存储 Kubernetes 集群的敏感数据,如私钥和机密。etcd
的妥协是api-server
成分的妥协。集群管理员在设置etcd
时要特别注意。
接下来,我们来看看kube-scheduler
。正如我们在 第 1 章中已经讨论过的,Kubernetes 架构kube-scheduler
负责将一个节点分配给一个 pod。一旦 Pod 被分配给一个节点,kubelet
执行 Pod 。kube-scheduler
首先对 pod 可以运行的节点集进行过滤,然后根据每个节点的评分,将 pod 分配给过滤后得分最高的节点。kube-scheduler
组件的折衷会影响集群中 Pod 的性能和可用性。
要保护kube-scheduler
,您应该执行以下操作:
- 禁用剖析:剖析
kube-scheduler
暴露系统细节。将--profiling
设置为false
会减少的攻击面。 - 禁用与 kube-scheduler 的外部连接:应禁用
kube-scheduler
的外部连接。AllowExtTrafficLocalEndpoints
设置为true
,启用与kube-scheduler
的外部连接。确保使用--feature-gates
禁用该功能。 - 启用设备:默认情况下,
kube-scheduler
启用AppArmor
。确保kube-scheduler
没有禁用AppArmor
。
在 Minikube 上,kube-scheduler
配置如下:
$ps aux | grep kube-scheduler
root 3939 0.5 2.0 144308 41640 ? Ssl 01:03 0:02 kube-scheduler --authentication-kubeconfig=/etc/kubernetes/scheduler.conf --authorization-kubeconfig=/etc/kubernetes/scheduler.conf --bind-address=0.0.0.0 --kubeconfig=/etc/kubernetes/scheduler.conf --leader-elect=true
与kube-apiserver
类似,调度程序也没有遵循所有的安全最佳实践,例如禁用概要分析。
kube-controller-manager
管理集群的控制回路。它通过应用编程接口服务器监控集群的变化,旨在将集群从当前状态移动到所需状态。默认情况下,kube-controller-manager
附带多个控制器管理器,例如复制控制器和名称空间控制器。kube-controller-manager
的妥协可能导致对集群的更新被拒绝。
要保护kube-controller-manager
,您应该使用- -use-service-account-credentials
,当与 RBAC 一起使用时,确保控制回路以最低权限运行。
在 Minikube 上,kube-controller-manager
配置如下:
$ps aux | grep kube-controller-manager
root 3927 1.8 4.5 209520 90072 ? Ssl 01:03 0:11 kube-controller-manager --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf --bind-address=0.0.0.0 --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-signing-cert-file=/var/lib/minikube/certs/ca.crt --cluster-signing-key-file=/var/lib/minikube/certs/ca.key --controllers=*,bootstrapsigner,tokencleaner --kubeconfig=/etc/kubernetes/controller-manager.conf --leader-elect=true --requestheader-client-ca-file=/var/lib/minikube/certs/front-proxy-ca.crt --root-ca-file=/var/lib/minikube/certs/ca.crt --service-account-private-key-file=/var/lib/minikube/certs/sa.key --use-service-account-credentials=true
接下来,让我们谈谈保护 CoreDNS。
kube-dns
是 Kubernetes 集群的默认域名系统 ( 域名系统)服务器。DNS 服务器帮助内部对象(如服务、容器和容器)相互定位。kube-dns
由三个容器组成,详细如下:
kube-dns
:这个容器使用 SkyDNS 来执行 DNS 解析服务。dnsmasq
:轻量级 DNS 解析器。它缓存来自 SkyDNS 的响应。sidecar
:监控的运行状况,并处理域名系统的指标报告。
kube-dns
从 1.11 版本开始就被取代了,因为 dnsmasq 的安全漏洞和 SkyDNS 的性能问题。CoreDNS 是提供kube-dns
所有功能的单一容器。
要编辑 CoreDNS 的配置文件,可以使用kubectl
,如下所示:
$ kubectl -n kube-system edit configmap coredns
默认情况下,Minikube 上的 CoreDNS 配置文件如下所示:
# Please edit the object below. Lines beginning with a '#'
# will be ignored, and an empty file will abort the edit.
# If an error occurs while saving this file will be
# reopened with the relevant failures.
apiVersion: v1
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf
cache 30
loop
reload
loadbalance
}
要保护 CoreDNS,请执行以下操作:
-
确保健康插件没有被禁用:
health
插件监控核心域名系统的状态。它用于确认 CoreDNS 是否已启动并运行。通过在Corefile
的待启用插件列表中添加health
来启用。 -
为 CoreDNS 启用 istio:
istio
是一个服务网格,Kubernetes 使用它来提供服务发现、负载平衡和身份验证。默认情况下,它在 Kubernetes 中不可用,需要作为外部依赖项添加。您可以通过启动istio
服务并将istio
服务的代理添加到配置文件中来将istio
添加到您的集群中,如下所示:global:53 { errors proxy . {cluster IP of this istio-core-dns service} }
现在我们已经了解了集群组件的不同配置,重要的是要认识到,随着组件变得更加复杂,将会添加更多的配置参数。集群管理员不可能记住这些配置。因此,接下来,我们讨论一种工具,它可以帮助集群管理员监控集群组件的安全状态。
互联网安全中心 ( CIS )发布了 Kubernetes 的基准,集群管理员可以使用该基准来确保集群遵循推荐的安全配置。发布的 Kubernetes 基准测试超过 200 页。
kube-bench
是一个用 Go 编写并由 Aqua Security 发布的自动化工具,运行 CIS 基准测试中记录的测试。测试用 YAML 非标记语言 ( YAML )编写,很容易进化。
kube-bench
可以直接使用kube-bench
二进制在节点上运行,如下所示:
$kube-bench node --benchmark cis-1.4
对于在gke
、eks
和aks
上托管的集群,kube-bench
作为一个 pod 运行。一旦 pod 完成运行,您可以查看日志以查看结果,如以下代码块所示:
$ kubectl apply -f job-gke.yaml
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
kube-bench-2plpm 0/1 Completed 0 5m20s
$ kubectl logs kube-bench-2plpm
[INFO] 4 Worker Node Security Configuration
[INFO] 4.1 Worker Node Configuration Files
[WARN] 4.1.1 Ensure that the kubelet service file permissions are set to 644 or more restrictive (Not Scored)
[WARN] 4.1.2 Ensure that the kubelet service file ownership is set to root:root (Not Scored)
[PASS] 4.1.3 Ensure that the proxy kubeconfig file permissions are set to 644 or more restrictive (Scored)
[PASS] 4.1.4 Ensure that the proxy kubeconfig file ownership is set to root:root (Scored)
[WARN] 4.1.5 Ensure that the kubelet.conf file permissions are set to 644 or more restrictive (Not Scored)
[WARN] 4.1.6 Ensure that the kubelet.conf file ownership is set to root:root (Not Scored)
[WARN] 4.1.7 Ensure that the certificate authorities file permissions are set to 644 or more restrictive (Not Scored)
......
== Summary ==
0 checks PASS
0 checks FAIL
37 checks WARN
0 checks INFO
调查状态为FAIL
的支票非常重要。你的目标应该是零检查失败。如果由于任何原因这是不可能的,您应该为失败的检查制定一个风险缓解计划。
kube-bench
是监控遵循安全最佳实践的集群组件的有用工具。建议添加/修改kube-bench
规则以适合您的环境。大多数开发人员在启动一个新集群时运行kube-bench
,但是定期运行它来监控集群组件是否安全是很重要的。
在本章中,我们查看了每个主节点和节点组件的不同安全敏感配置:kube-apiserver
、kube-scheduler
、kube-controller-manager
、kubelet
、CoreDNS 和etcd
。我们学习了如何保护每个组件。默认情况下,组件可能不会遵循所有的安全最佳实践,因此集群管理员有责任确保组件的安全。最后,我们看一下kube-bench
,它可以用来了解您运行的集群的安全基线。
理解这些配置并确保组件遵循这些清单以减少妥协的机会非常重要。
在下一章中,我们将研究 Kubernetes 中的身份验证和授权机制。我们在这一章中简要地讨论了一些准入控制者。我们将深入探讨不同的准入控制器,最后讨论如何利用它们来提供更细粒度的访问控制。
- 什么是基于令牌的身份验证?
- 什么是
NodeRestriction
入场控制器? - 如何确保数据在
etcd
静止时加密? - 为什么 CoreDNS 取代了
kube-dns
? - 如何在一个埃拉斯蒂克 Kubernetes 服务 ( EKS )集群上使用
kube-bench
?
有关本章所涵盖主题的更多信息,您可以参考以下链接:
- 独联体基准:https://www.cisecurity.org/benchmark/kubernetes/
- github(“t0”):1231 t1]https://github . com/aqua security/kube-bench*