category
鉴于Kubernetes的受欢迎程度和高采用率,其安全性应始终放在首位。我们提供了关于保持主节点、API服务器等、RBAC和网络策略安全的重要提示和建议。
尽管Kubernetes在市场上相对新颖,但截至今年年初,它现在是开发者最想要的第三大平台。考虑到该平台的受欢迎程度和高采用率,开发人员必须确保始终优先考虑Kubernetes的安全性。
在之前的一篇文章中,我们概述了如何保护云原生系统的4C(云、集群、容器和代码),以及深入应用最小权限和防御等安全原则的重要性。我们还解决了可能影响Kubernetes部署的常见风险和威胁。
为了帮助开发人员进一步确保Kubernetes部署尽可能安全,我们详细介绍了保护Kubernete集群的一些基本步骤。
[Read our guide on securing worker nodes]
如果您使用托管服务(如Azure Kubernetes Service(AKS)、Amazon Elastic Kubernets Service(Amazon EKS)或Google Kubernete Engine(GKE))运行集群,则云提供商将处理控制平面安全性。尽管如此,最好更好地了解可用的安全选项,并确保您的云提供商遵循建议的安全最佳实践。
但是,如果出于任何合规或业务相关的原因,您必须部署和维护自己的控制平面,则必须在您的Kubernetes集群中仔细应用此处讨论的设置,以更好地保护您的整个Kubernete环境。
控制平面
Kubernetes控制平面在管理工作节点时充当集群的主节点。正是大脑使这个复杂的系统保持运转和良好的状态。
Figure 1. A diagram of a Kubernetes cluster and its components
根据上图,为集群供电的主要组件位于控制平面中。该图还显示,所有通信都通过kube API服务器或kube-apiserver,这基本上是一个REST API,定义并控制Kubernetes的所有管理和操作功能。恶意行为者将试图访问kube apiserver和控制平面,一旦这些被破坏,他们就可以通过部署新的pod、编辑已经运行的pod,甚至完全删除pod来操纵pod(放置容器的地方),从而破坏整个集群。
如何加固控制平面及其主要部件
为了保护控制平面的安全,您可以做的一件基本事情是对最关键的Kubernetes文件执行完整性监控。这样做,配置中的任何更改都会立即提醒您。从Kubernetes的安全角度来看,关键文件是那些在受到攻击时会影响整个集群的文件。最新的CIS Kubernetes Benchmark v1.5.1中详细介绍了您需要持续监控的主要文件和目录的列表,以及建议的所有权和权限级别。需要注意的是,其中大多数都是Kubernetes安装的默认值,因此您已经有了一个基线:
File or directory |
Recommended ownership |
Recommended permission (or more restrictive) |
/etc/kubernetes/manifests/kube-apiserver.yaml |
root:root |
644 |
/etc/kubernetes/manifests/kube-controller-manager.yaml |
root:root |
644 |
/etc/kubernetes/manifests/kube-scheduler.yaml |
root:root |
644 |
/etc/kubernetes/manifests/etcd.yaml |
root:root |
644 |
Container Network Interface file |
root:root |
644 |
/var/lib/etcd |
etcd:etcd |
700 |
/etc/kubernetes/admin.conf |
root:root |
644 |
/etc/kubernetes/scheduler.conf |
root:root |
644 |
/etc/kubernetes/controller-manager.conf |
root:root |
644 |
/etc/kubernetes/pki/ |
root:root |
---* |
Kubernetes PKI certificate file: /etc/kubernetes/pki/*.crt |
root:root |
644 |
Kubernetes PKI key file: /etc/kubernetes/pki/*.key |
root:root |
600 |
* The CIS Kubernetes Benchmark doesn't state recommended permissions for this directory
API服务器
仍然有一些组织犯了让kube apiserver公开的严重错误。向公众公开API服务器是攻击者最常见的切入点,并允许他们接管您的集群。尽管现在默认情况下没有启用,但一些工程师最终可能会出于测试目的启用它,并在测试完成后忘记恢复这些更改。随着时间的推移,这个问题可能会升级,尤其是在疫情期间,大多数人都在家工作。目前,有攻击者和机器人不断在互联网上搜索开放的Kubernetes API服务器,以便他们能够强行进入并试图利用它们。特斯拉就是这样,他们的一台Kubernetes控制台被发现可以公开访问,并被滥用进行非法加密货币挖矿。
如何保护kube apiserver
重要的是要学会如何检查你的kube apiserver没有暴露在互联网上。一种简单的检查方法是尝试从外部IP访问API服务器。如果你能做到这一点,那就意味着其他机器也有能力做到这一步——当然,除非你将其限制在自己的IP上。
您可以尝试这个curl请求,看看您的API是公开的还是其他的:https://my-control-plane-ip:6443/api
如果您从这个curl请求中得到了响应,比如下面的请求,那么这意味着您的API是公开的,并向世界公开:
一个示例的响应-执行后的请求
图2:执行curl请求以检查API是否可公开访问后的响应示例
尽管如此,得到这样的回应不应该自动引起恐慌。幸运的是,有不同的方法来应用修复,这取决于您的工程师如何访问API。然而,我们认为,最好和最安全的选择如下。
允许工程师仅通过内部网络(或公司VPN)访问集群API。这可以通过设置适当的防火墙或安全组规则(在AWS的情况下)轻松实现。这里你唯一需要考虑的是紧急情况的可能性,在此期间,你的集群管理员无法随时访问公司的笔记本电脑或VPN。在这种情况下,需要通过安全列出集群管理员的IP(最好是特定的API端口)来授予对集群的访问权限。
您还可以通过主授权网络设置限制对GKE上集群的访问,从而在有人能够篡改您的防火墙规则的情况下创建另一层保护。以下是执行此操作的命令:
gcloud container clusters create --enable-master-authorized-networks --master-authorized-networks=CIDR
有关此功能的更多信息,请参阅GKE的官方文档。
您可以做的另一件事是通过在控制平面节点上运行以下简单命令来检查和验证您的kube apiserver是否具有正确的推荐安全设置:
ps -ef | grep kube-apiserver
以下是此命令的输出示例:
检查kube apiserver是否存在的输出
图3。检查kube apiserver是否具有正确的推荐安全设置的输出
由于这是一个刚刚通过kubeadm工具和默认设置创建的集群,我们可以分析这些值。下面的列表包含CIS Foundation Benchmarks建议在kube apiserver中应用的一些安全配置:
CIS # |
Name |
Value |
Default |
1.2.1 |
Ensure that the –anonymous-auth argument is set to false or not set |
Not set |
Y |
1.2.2 |
Ensure that the –basic-auth-file argument is not set |
Not set |
Y |
1.2.3 |
Ensure that the –token-auth-file parameter is not set |
Not set |
Y |
1.2.4 |
Ensure that the –kubelet-https argument is set to true or doesn't exist |
Not set |
Y |
1.2.5 |
Ensure that the –kubelet-client-certificate and –kubelet-client-key arguments are set as appropriate |
/etc/kubernetes/pki/apiserver-kubelet-client.crt /etc/kubernetes/pki/apiserver-kubelet-client.key |
Y |
1.2.6 |
Ensure that the –kubelet-certificate-authority argument is set as appropriate |
N/S |
N |
1.2.7 |
Ensure that the –authorization-mode argument is not set to AlwaysAllow |
Node, RBAC |
Y |
1.2.8 |
Ensure that the –authorization-mode argument includes Node |
Node, RBAC |
Y |
1.2.9 |
Ensure that the –authorization-mode argument includes RBAC |
Node, RBAC |
Y |
1.2.10 |
Ensure that the admission control plugin EventRateLimit is set |
Not set |
N |
1.2.11 |
Ensure that the admission control plugin AlwaysAdmit is not set |
Not set |
N |
1.2.12 |
Ensure that the admission control plugin AlwaysPullImages is set |
Not set |
N |
1.2.13 |
Ensure that the admission control plugin SecurityContextDeny is set if PodSecurityPolicy is not used |
Not set |
N |
1.2.14 |
Ensure that the admission control plugin ServiceAccount is set |
Not set |
N |
1.2.15 |
Ensure that the admission control plugin NamespaceLifecycle is set |
Not set |
N |
1.2.16 |
Ensure that the admission control plugin PodSecurityPolicy is set |
Not set |
N |
1.2.17 |
Ensure that the admission control plugin NodeRestriction is set |
NodeRestriction |
Y |
1.2.18 |
Ensure that the –insecure-bind-address argument is not set |
Not set |
Y |
1.2.19 |
Ensure that the –insecure-port argument is set to 0 |
0 |
Y |
1.2.20 |
Ensure that the –secure-port argument is not set to 0 |
6443 |
Y |
1.2.21 |
Ensure that the –profiling argument is set to false |
Not set |
N |
1.2.22 |
Ensure that the –audit-log-path argument is set |
Not set |
N |
1.2.23 |
Ensure that the –audit-log-maxage argument is set to 30 or as appropriate |
Not set |
N |
1.2.24 |
Ensure that the –audit-log-maxbackup argument is set to 10 or as appropriate |
Not set |
N |
1.2.25 |
Ensure that the –audit-log-maxsize argument is set to 100 or as appropriate |
Not set |
N |
1.2.26 |
Ensure that the –request-timeout argument is set as appropriate |
Not set |
N |
1.2.27 |
Ensure that the –service-account-lookup argument is set to true |
Not set |
N |
1.2.28 |
Ensure that the –service-account-key-file argument is set as appropriate |
/etc/kubernetes/pki/sa.pub |
Y |
1.2.29 |
Ensure that the –etcd-certfile and –etcd-keyfile arguments are set as appropriate |
/etc/kubernetes/pki/apiserver-etcd-client.crt /etc/kubernetes/pki/apiserver-etcd-client.key |
Y |
1.2.30 |
Ensure that the –tls-cert-file and –tls-private-key-file arguments are set as appropriate |
/etc/kubernetes/pki/apiserver.crt /etc/kubernetes/pki/apiserver.key |
Y |
1.2.31 |
Ensure that the –client-ca-file argument is set as appropriate |
/etc/kubernetes/pki/ca.crt
|
Y |
1.2.32 |
Ensure that the –etcd-cafile argument is set as appropriate |
/etc/kubernetes/pki/etcd/ca.crt |
Y |
1.2.33 |
Ensure that the –encryption-provider-config argument is set as appropriate |
Not set |
N |
1.2.34 |
Ensure that encryption providers are appropriately configured |
Not set |
N |
1.2.35 |
Ensure that the API server only makes use of strong cryptographic ciphers |
Not set |
N |
从该表中可以看出,当使用kubeadm工具从头开始安装Kubernetes时,默认情况下,CIS Foundation Benchmarks推荐的安全设置中至少有一半没有设置或启用。在将集群投入生产之前,请考虑评估和设置这些配置。
RBAC授权
既然您已经限制了对API服务器的访问,并减少了可以访问它的人数,那么如何确保访问集群的工程师不会造成任何损害?答案是RBAC。
RBAC将允许您配置谁可以访问集群中的内容。我们强烈建议您在集群中启用RBAC授权,尤其是生产集群。您还可以限制任何用户访问所有控制平面pod所在的kube系统名称空间。
Kubernetes中的RBAC在使用以下标志启动时通过kube-api服务器启用:
–authorization-mode=RBAC
如何检查是否启用了RBAC
如图3所示,在最新版本中,RBAC授权模块已经默认启用;您所要做的就是创建适当的角色,并将它们分配或绑定到一组特定的用户。但请记住,恶意用户仍然可以禁用RBAC。要检查RBAC是否已禁用,您可以运行我们之前运行的相同命令,以检查控制平面上的Kube API服务器配置,并查找–authorization-mode=RBAC:
ps-ef|grep kube apiserver
使用RBAC授权时,有四种API对象可以使用:
- 角色此对象将包含表示命名空间中的一组权限的规则。
- 角色绑定。此对象只是将角色的权限授予一个或多个用户。
- ClusterRole。此对象还将包含表示一组权限的规则,但它不绑定到命名空间,并且将应用于集群级别
- ClusterRoleBinding。与RoleBinding类似,它也为一组用户授予ClusterRole权限。
Role和ClusterRole上提到的这些设置权限通常由Verb和Noun的组合组成,后者表示Kubernetes对象/资源。一些例子包括:
- Get Pods
- List Secrets
- Watch ConfigMaps
以下是角色对象在YAML文件中的表示方式:
-YAML中角色对象的一个实例
图4。YAML中的角色对象示例允许用户在默认命名空间上获取、监视和列出pod
图片来源:Kubernetes.io
用户如何通过RoleBindings与角色相关
图5。用户如何通过RoleBindings与角色相关(对于ClusterRoles和ClusterRoleBindings也是如此)
需要注意的是,在Role(或ClusterRole)和一组用户之间创建绑定后,您将无法更改它所引用的Role或ClusterRole。如果需要这样做,您将首先需要删除绑定对象,然后为该对象创建替换对象。
关于如何在Kubernetes中实现RBAC的更多细节和一些具体示例,可以在官方文档中找到。
etcd
etcd是集群的主要数据存储位置——这意味着所有集群对象都保存在这里。由于其层次性和标准化特性,Kubernetes部署使用它来存储RESTneneneba API对象和安装配置。当蚀刻剂暴露在外时,可能会泄露关键数据。不幸的是,etcd错误配置仍然猖獗——今年我们在Shodan上看到了2600多个暴露的etcd服务。
How to secure the etcd
与任何数据存储系统一样,应将相同的安全原则应用于etcd。应实现并启用传输中和静止时的加密。要检查您的etcd是否配置了TLS加密,请在控制平面主机上键入以下命令:
ps -ef | grep etcd
之后,检查参数-cert file和-key file是否设置正确。如果不是,您将不得不修改位于/etc/kubernetes/manifests/eccd.yaml的etcd-pod规范文件,并用它们各自的文件路径设置这些参数,例如:
–cert-file= –key-file=
截至今天,当前的Kubernetes默认安装已经为etcd设置了正确的密钥和证书以及TLS加密。更详细的说明可以在CIS Kubernetes基准测试的第2.1项中找到。
如果攻击者以某种方式绕过API服务器,能够将对象直接操作到etcd中,则这与完全访问整个集群相同。攻击者将能够创建pod、读取机密和查看用户凭据等敏感数据。为了防止这种情况发生,除了启用传输中的加密外,还需要启用静态加密,以防止数据泄露或篡改etcd数据。
在检查和保护传输中的数据传输后,我们现在可以继续加密所有静止的etcd数据,并确保集群内数据的更高安全性。
要检查是否已启用静止加密,请在kube apiserver设置中查找此参数:
–encryption-provider-config
如果未启用,则需要创建一个EncryptionConfiguration对象并指向
–加密提供程序配置到该文件位置。之后,重新启动API服务器,应该应用加密。以下是EncryptionConfiguration对象的示例,该对象将在将所有机密存储到etcd之前对其进行加密:
EncryptionConfiguration的示例
图6。加密机密的EncryptionConfiguration对象的示例
图片来源:Kubernetes.io
在使用–encryption provider config参数重新启动kube apiserver后,数据在写入etcd时将被加密,任何创建或更新的机密在存储到etcd时都应被加密。有关此对象的不同字段和加密提供程序的更多详细信息,请参阅官方文档。
网络
默认情况下,集群中的所有pod都可以与同一集群上的任何其他pod通信,包括来自不同名称空间的pod,这包括托管控制平面的主kube系统名称空间。除非更改,否则这是在安装Kubernetes和部署集群时配置的网络策略。
现在,让我们假设攻击者能够将pod部署到集群上的任何命名空间中。此外,该pod可以访问管理Kubernetes集群的所有pod,这些pod位于kube系统名称空间中。你能看到这种情况下的问题吗?
如何限制Pod通信
网络策略可以帮助解决这个pod开放通信问题。网络策略指定pod组如何相互通信以及其他网络端点之间的通信。NetworkPolicy API资源使用标签来选择pods,并定义规则来指定所选pods允许的流量类型。这些策略可以帮助您限制pod或命名空间之间的访问。所有的访问都可以通过YAML文件中的标签进行配置,例如,允许您阻止pod访问kube系统命名空间上的其他pod。
以下是网络策略的示例:
一个典型的Kubernetes网络策略
图7。Kubernetes网络策略示例
来源:Kubernetes.io
一个重要的注意事项:您需要使用支持NetworkPolicy对象的网络解决方案或容器网络接口(CNI);否则,它将不会对集群产生任何影响。重要的是要了解网络插件及其功能,并能够比较最常用的CNI插件,看看哪一个最适合您的系统。
我们在GitHub上创建了一个Kubernetes安全列表,其中包含讨论Kubernete安全的博客、文章、工具和视频,供那些想学习加强Kubernets部署技巧的人使用。
在本系列的第二部分中,我们将讨论如何保护工作节点、kubelet和pod。我们还将处理设置审核日志的问题,这将使您更清楚地了解集群中正在发生的事情。
- 登录 发表评论
- 5 次浏览
Tags
最新内容
- 1 day 11 hours ago
- 1 day 14 hours ago
- 1 day 14 hours ago
- 4 days 6 hours ago
- 4 days 13 hours ago
- 4 days 14 hours ago
- 4 days 14 hours ago
- 4 days 14 hours ago
- 1 week 1 day ago
- 1 week 1 day ago