Redian新闻
>
Kubernetes DevSecOps 实践

Kubernetes DevSecOps 实践

公众号新闻

Kubernetes 安全性

在执行发布之前和之后,安全管理员需要采取一系列详尽的安全措施。当涉及到一个拥有多个应用程序且更容易受到攻击的大型组织时,这个数字会增加。现在,考虑到在每次发布之前都需要考虑所有这些因素。

为确保系统的安全性需要投入多少时间和精力?这是一个重大问题,因为冗长的安全审计过程会使明确定义且自动化的 DevOps 流程变得毫无用处。自动化的测试和发布流水线的目标是快速且一致地发布。这意味着在冗长的安全审计过程完成之时,开发团队可能已经发布了应用程序的另一个版本。一旦该版本经过审计并准备好发布,将会有两个更高版本的应用程序出现。你可以想象问题的严重程度。

DevSecOps如何解决这个问题?

在单体架构的世界中,等待开发团队完成产品以便开始进行安全审计是完全可以接受的。由于发布并不那么频繁,安全团队在发布之间有足够的时间来完成他们的工作。此外,微服务架构增加了攻击者可能进行攻击的方式。整个集群通过 API 端点进行通信,并且一个平均集群中通常有大量的 Kubernetes 资源,这些资源都可以被利用。此外,开发人员倾向于使用其他人创建的资源(例如镜像),而他们无法控制这些资源的安全性。虽然单块系统可能不会出现这么多问题,但微服务架构使你的系统更容易受到攻击,从而使安全团队的工作变得更加困难。

DevSecOps 提出的解决方案是将安全审计阶段与 DevOps 流程的其他部分相结合,将其整合到 DevOps 生命周期中。这意味着开发人员自身需要确保他们开发的内容符合正确的安全标准。

尽管安全团队仍然存在以确保执行安全策略,但保护应用程序的主要部分将不再由他们来完成。

对于开发人员来说是什么样的情况?

现在,你可能认为这对开发人员来说是额外的工作负担,从某种意义上说你可能是正确的。毕竟,发布工作代码将由你来完成。然而,可用的自动化工具将会为你处理很多事情。为建立 DevOps 工作流程需要一些开销,但从那一点开始,一切都应该自动化。通常你会设置每个拉取请求运行的构建。这些构建将包含一系列流水线,从你的分支获取原始源代码,构建它,运行自动化测试,并最终执行一整套安全扫描,以确保你的分支符合发布稳定代码的所有要求。

例如,如果你的最终产品是发布到容器仓库的镜像,流水线将首先使用类似 Sonarqube 的工具扫描你的代码,以验证它是否符合必要的编码规范,之后将构建实际的镜像。然后,将扫描镜像的依赖项,并与数据库进行交叉检查,以查看你的镜像是否存在任何已知的漏洞。之后可能会有其他检查起到作用,但这取决于你正在创建的镜像类型。

测试过程不需要止步于此。一旦将你的更改与主分支合并,需要运行集成测试以确保你的更改与其他更改相容。一旦你的镜像到达容器仓库,仓库会定期运行测试以确保没有新的漏洞可能影响到你的镜像。

因此,最终你作为开发人员只需要记住这些概念,而不需要主动管理你的应用程序的安全性。

最终,你将拥有一个与开发周期整合的安全系统,这将使你编写的代码更加安全和无缺陷,同时将减轻安全团队的工作量,确保更快的发布周期。

最大的优势在于你将获得关于代码状态的即时反馈。

因此,如果你的代码存在一些缺陷或问题,它将在你自己的分支内部被捕捉到,这意味着没有产生任何后果。

那么这些安全措施意味着什么?发布周期的哪些部分需要整合安全步骤?让我们深入探讨一些不同的方法,以确保你的 Kubernetes 集群的安全性。

Kubernetes 安全性

作为个人开发者,安全性可能不是我们首要考虑的问题。我们主要关注满足任务需求,将访问控制等事项留待以后处理。在使用 Kubernetes 时,我们往往认为安全方面的事情是理所当然的。

由于 Kubernetes 被设计时考虑了安全性,并且由于任何新兴技术的作者都需要充分关注安全性,才能考虑商业化使用,Kubernetes 生态系统相对较为安全。然而,对于设置大规模集群供内部和客户使用的大型组织来说,拥有大量安全措施非常重要。

大多数大型组织都有专门的团队负责处理授权和应用程序安全性。Kubernetes 依赖于微服务,使用了数千个第三方应用程序进行运行。每个这些应用程序都有可能引入安全漏洞,这是不可接受的。由于由于处理凭据不当导致的客户遭受侵害可能给企业造成巨大损失,因此组织有兴趣确保他们雇佣了了解安全最佳实践的 DevOps 工程师。因此,让我们深入探讨 Kubernetes 安全性。

保护镜像

在使用第三方镜像时,有可能镜像的作者可能没有采取必要的措施来保护镜像。因此,确保镜像符合组织设定的安全标准就是你的责任。然而,如果你创建的镜像用于内部使用或在镜像托管站点上免费提供,那么你应该采取几个步骤来保护你的镜像。毕竟,如果攻击者通过利用运行你的镜像的容器来获取对集群的访问权限,那将非常尴尬。那么在这里可以做些什么呢?

检查你的依赖关系

除非你正在构建的镜像只执行简单的任务,否则你可能会使用一个基础镜像或者一系列镜像来构建你的镜像。然后你会在这个基础镜像之上构建你的镜像。这是可能出错的地方,因为你对基础镜像及其内容控制很少。此外,你可能会有与底层操作系统交互并执行一些命令的镜像,这些命令可能会允许攻击者在系统中看到一个后门。规避这个问题的最简单方法是尽可能使用较少的依赖项。你依赖的镜像越多,安全风险就越大。在选择依赖项时,确保你只选择一个具有你所需内容的镜像。例如,如果你想使用 curl,那么没有理由选择一个具有 curl/wget/其他请求处理命令的通用镜像,而不是选择提供 curl 的镜像。

镜像扫描: 你可能认为上述所有步骤听起来很复杂,但事实并非如此,因为存在镜像扫描。镜像扫描允许你自动查看一个定期更新的漏洞数据库,并将你的镜像及其依赖关系与之进行比较。通常,你不会手动构建商业级别的镜像,而是允许流水线为你完成构建。你只需在镜像本身构建完成后添加镜像扫描作为一个额外的步骤即可。

但是,在构建镜像后还可能添加漏洞,并且如果你的镜像依赖于其他镜像,漏洞也可能通过这些其他镜像引入。其结果是,你不能只扫描你的镜像一次,将其推送到容器仓库,然后忘记它。你需要确保所有已存在于注册表中的镜像定期进行扫描。在这方面,你可能会得到一些帮助,这取决于你选择的镜像注册表。例如,GCR、AWS ECR、Docker Hub 等注册表都具有内置的仓库镜像扫描功能。但是,如果你托管自己的容器注册表,则可能需要手动执行这些操作。

一个很好的镜像扫描服务示例是 Snyk。它非常简单易用,你只需要运行一个命令:

docker scan <镜像名称>

在发布流水线上运行此命令将揭示你的镜像中的任何漏洞。另一个可以使用的优秀工具是 Sysdig。它们提供与 Snyk 类似的容器安全性服务,允许你将镜像扫描无缝集成到现有流水线中。

你还将获得持续合规性,确保发布后不会发现影响你的镜像的新漏洞。这包括检查你的配置,确保镜像内部使用的任何凭据未被泄露,并保护你的镜像免受内部威胁。你还可以获得镜像合规性,以证明你的镜像符合组织设定的任何标准。它还可以与你现有的 Kubernetes 集群以及基础架构即代码(IaC)平台无缝集成。

用户服务用户

如果你使用具有无限制访问权限的用户(例如 root 用户)来运行你的容器,那么获得对容器访问权限的攻击者很容易获得主机系统的访问权限,因为他们已经具有了提升的特权。解决这个问题的方法是在创建容器时创建一个服务用户,然后确保容器由该非特权服务用户处理。这样,即使攻击者获得对容器的访问权限,他们也无法对服务账户做太多事情,除非他们还能够获取 root 用户的访问权限。

那么你该如何处理呢?Docker 默认以 root 用户身份运行命令,你需要通过在 Dockerfile 中将服务用户添加到用户组来更改此设置。 如果你已经有一个现有的用户组,可以使用 usermod 命令为你添加服务用户,或者你可以使用以下命令创建/添加用户组:

RUN groupadd -r <应用名称> && useradd -g <应用名称> <应用名称>

下一步是使用 chown 命令限制用户在此镜像中的操作:

RUN chown -R <应用名称>:<应用名称> /app

接下来,切换到该用户,以便容器始终以该用户而不是 root 用户运行:

USER <应用名称>

现在,你的容器将以你在此处指定的用户身份运行,并增加了一层保护。但是,当你使用该镜像启动一个 Pod 时,你必须确保不要在 yaml 中配置错误,以免覆盖镜像命令并以 root 用户身份运行你的 Pod。为确保这一点,添加以下命令:

allowPrivilegeEscalation: false

在这里可以了解更多信息。

保持严密的用户组和权限

在创建镜像时需要采取所有上述预防措施,而不是在部署之前。然而,这仅仅是第一步。一旦你部署了镜像,并从这些镜像启动了 Pod,你需要采取进一步的措施来防止攻击者入侵你的系统。普遍认为系统的用户是最薄弱的环节,虽然用户需要能够以不允许被利用的方式使用系统,但你的任务是假设一定会发生漏洞,并做好相应的准备。请注意,你的集群可能被属于实际用户和自动化系统/服务账户的帐户访问。所有这些账户都需要得到保护。如果你给组织中的每个用户都分配了管理员权限,那么如果其中一个帐户受到攻击,整个系统都将处于风险之中。或者,如果每个用户都被分组到一个非常具体的权限集合中,只允许用户进行他们需要的操作,而不允许进行其他操作,那么即使一个帐户被攻击,损害也会有限。

幸运的是,Kubernetes 提供了一种解决方案,使你不必花费大量时间进行设置。RBAC(基于角色的访问控制)允许你指定角色,这些角色进而指定访问权限。因此,如果你想指定对集群日志的读取访问权限,但仅限于特定命名空间的日志,你可以创建一个相应的角色。一旦你有了角色,你可以将此角色分配给任何用户,他们将自动获得该角色授予的所有权限。因此,如果你有一个使用特定权限集的团队,你可以创建一个具有该权限集的角色,并将角色分配给每个成员(或将角色分配给组中的成员),而无需逐个分配每个权限。与其他所有内容一样,你将 RBAC 定义为符合标准 Kubernetes YAML 格式的 Kubernetes 资源。你可以在 RBAC101 部分详细了解 RBAC。

集群内部网络策略

既然你已经防止了对集群的外部攻击,那么你可以假设所有的安全措施都会失败,攻击者最终将设法进入集群。这意味着你现在还需要确保你的集群内部也受到保护。

默认情况下,集群中的所有 Pod 都以某种形式相互连接。它们中的大多数可以通过 localhost 访问彼此,这意味着如果有人成功进入你的集群并找到一台 Pod,其他所有的 Pod 也将被攻击者轻易获取。解决这个问题的方法与我们处理用户访问的解决方案相同:限制访问权限。如果你限制每个 Pod 的通信能力,这将在一定程度上解决问题。网络策略仍然是一个 Kubernetes 资源,类型为 NetworkPolicy,它允许你指定每个资源所接受的 IP 范围。

虽然网络策略对于限制访问在小型集群和少量 Pod 方面非常好,但在大型集群中可能会出现一些重复和复杂性。考虑使用 Istio 和 Linkerd 等服务网格来增强安全性(以及添加其他集群范围的功能),通过自动为每个 Pod 添加代理来独立管理 Pod 通信。你可以在 ServiceMesh101 部分了解更多信息。

加密

尽管已经采取了上述所有措施,Pod 仍然需要进行通信。毕竟,这就是微服务架构的目的所在。这就是加密发挥作用的地方。默认情况下,Pod 之间的所有通信都是未加密的。这意味着即使攻击者无法直接访问 Pod,他们仍然可以获取其他 Pod 的日志。通过使用互相认证的传输层安全性(mutual TLS),可以解决这个问题,对 Pod 之间的流量进行加密。这也是 Istio 的一部分,这就是为什么在大型集群中使用服务网格始终是推荐的。

Base64 密钥

这在 Kubernetes 中非常常见,我承认在处理密钥时,我经常简单地将它们编码为 Base64。默认情况下,Kubernetes 环境中的大多数密钥都以 Base64 编码,并以原样存储。这是一个巨大的安全风险,因为任何人都可以解码这个字符串并完全访问你的密钥。Kubernetes 以 EncyptionConfiguration 资源的形式提供了解决方案,但你仍然需要安全地存储加密密钥。像 AWS KMS 这样的密钥管理服务可以帮助你解决这个问题。你还可以跳过处理加密密钥,并使用密钥管理系统。

让我们来看看内置的 Kubernetes 加密资源。这个资源,像往常一样,是一个名为 EncryptionConfiguration 的普通 yaml 资源文件:

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <BASE 64 ENCODED SECRET>
      - identity: {}

kind 在 yaml 文件的顶部进行定义,之后是键和它们各自的密钥。这些密钥被定义为一个提供器列表,这些提供器向请求它们的应用程序提供密钥。例如,如果应用程序请求 "key1" 的密钥,将匹配提供器并释放相关信息。如果没有匹配的提供器,将返回错误。要定义编码的密钥,可以使用在所有 Unix 机器上都存在的 base64 命令:

head -c 32 /dev/urandom | base64

将此值设置为你的密钥。接下来,你需要设置引用此资源文件的 kube-apiserver,这个文件配置了所有 API 对象的数据(这使得它成为处理加密数据的理想位置)。在文件上设置以下标志:

--encryption-provider-config你还需要重新启动 API 服务器以开始看到更改的效果。请注意,由于你的 API 服务器可以访问这些凭据,你必须限制对该文件的访问。为了测试你的密钥是否真正加密,首先创建一个普通的 Kubernetes 密钥:

kubectl create secret generic secret1 -n default --from-literal=mykey=mydata

然后使用 etcdctl CLI 命令从 etcd 中读取密钥:

ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 <arguments> | hexdump -C

最后,描述该密钥以确保密钥正确解密:

kubectl describe secret secret1 -n default

密钥是一个不错的起点,但通过使用定期更换的密钥,可以提供更多的保护。这意味着你的密钥将定期更改,即使攻击者能够获取你的密钥,他们使用它的时间可能已经过去了。然而,你可能会注意到一个大问题:停机时间。如果你要更改密钥,你还必须更改引用密钥的每个位置,并且在此过程中必须始终关闭系统。然而,如果你愿意经历一个稍微冗长的过程,你可以消除这种停机时间。

要做到这一点,你需要分阶段引入新密钥。首先生成新密钥并将其作为第二个密钥添加到提供器中,然后你需要重新启动 kube-apiserver。然后,将新密钥重新定位为键数组中的第一个密钥,然后再次重新启动 kube-apiserver。最后,获取所有命名空间中的所有密钥,并使用新密钥替换它们:

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

删除旧的解密密钥,因为它已经没有用处了。

保护 etcd

你的 etcd 存储了在 Kubernetes 集群中监视和维护资源所需的所有键值对。因此,它对你的集群具有全面的控制权,并且你的集群具有与 etcd 的一致联系的方式。如果攻击者能够访问 etcd,他们将能够控制你的集群,而且由于发生在 Pod 内部的任何更改都会报告给 etcd,他们也将获取这些信息的见解。由于攻击者无需使用控制平面和资源之间的 API,他们将几乎无障碍地访问你的集群,这是一个明显的问题。

解决这个问题非常简单。由于绕过的是 API 服务器,只需将 etcd 存储放在防火墙后面,只允许 API 服务器访问它。这样,攻击者即使获得对 etcd 的访问权限,也无法操纵集群。然而,你的 etcd 存储可能已经包含了一些敏感信息,你希望阻止攻击者读取这些数据。通过对 etcd 存储中的信息进行加密,可以帮助你解决这个问题。

安全策略

如果你是一个在规模较大的组织中工作的普通开发者,那么你很可能已经遵循了强制执行的一套集群安全策略。然而,如果你是一个较小组织的管理员,或者恰好是这些集群的管理员,那么你需要负责维护集群的安全性。开发者更关注于满足期限并推出产品,他们可能会忽视他们引入系统中的一些安全漏洞,作为管理员,你不可能监控他们推送的每个资源。相反,你可以在部署时启用强制执行的安全策略,如果资源不符合所需的安全标准,将阻止部署该资源。例如,如果有容器以 root 访问权限运行,你可以在部署之前将它们剔除并拒绝该资源。

Open Policy Agent 是一个支持这一点的优秀工具。OPA 使用统一的框架,可以应用于你的云原生堆栈,这意味着你的整个堆栈将使用一组策略工作。策略以声明性语言(称为 Rego)定义,并可对所有类型的 Kubernetes操作实施策略。你还可以检查资源上特定标签的存在、每个镜像的来源以及 Ingress 对象的有效性等。你还可以使用审计控制器来操作正在应用的资源,以使其符合策略。这包括为每个添加的 Pod 添加 Sidecar 容器,自动识别和替换托管在非公司仓库中的镜像,使用 taints 和 tolerations 来改变部署。学习如何使用他们的声明性语言并在你的集群上实施 OPA 的最佳方式是使用他们的交互式 playground。

灾难恢复

这里需要记住的关键一点是,尽管你可以增加攻击者的难度,但不能保证实施所有上述安全策略仍然可以防止你的数据遭受攻击。这就是灾难管理的作用。虽然你的 etcd 存储可能允许攻击者获取对集群的特权访问,但这不是你的集群最重要的部分。最重要的是你的数据。由于数据非常有价值,勒索软件是企业必须面对的常见问题,定期备份并安全存储数据是避免陷入这些情况的最佳方式。当然,你不必手动处理这个问题,因为 Kasten 提供了一个名为 K10 的出色解决方案。K10 可以定期自动备份你的数据,并允许你通过点击按钮恢复这些备份。它还提供端到端的安全性,确保你的备份也得到了保护。攻击者通常会预期存在备份,并可能针对它们进行攻击,这意味着你必须采取额外的措施防止你的备份被删除。

对数据进行快照,并在存储数据时应用加密,同时在传输数据时也进行加密。这意味着即使攻击者获取了数据,他们也无法阅读它。此外,你的备份可能会被攻击者损坏,你可以通过创建不可变备份来防止这种情况。这意味着备份无法更改(合理地说,备份在备份后不需要更改)或删除。K10 是一个集成的、易于使用的解决方案,甚至非程序员也可以使用它来管理集群安全。你甚至可以在此处获取有关如何使用 K10 的实践实验室。

备份数据只是需要备份的内容之一。你的集群本身不仅仅是由数据组成的。因此,如果攻击成功并导致系统离线,仅仅恢复数据是无法帮助你的。例如,如果你运行一个电子商务网站,那么你的集群即使停机几个小时也可能导致销售额下降,这是你想要避免的。这意味着你需要同时将你的集群和数据还原到以前的状态。K10 在这方面也可以帮助你,它可以对集群状态进行快照。然后在紧急情况下应用此状态,使你的集群恢复到之前的状态。这里仍然有一些可能出错的情况,你需要事先测试这些灾难恢复方法,以确保在遇到攻击情况时不会有任何意外。

为了让你的工作更轻松,K10 还允许你将系统恢复到与当前运行的 Kubernetes 环境不同的环境。这意味着即使你在 AKS 上运行你的集群,你也可以将其恢复到 Amazon EKS 上。你甚至可以切换 Kubernetes 版本(只要你的资源支持),这意味着你可以创建一个攻击者无法预测的全新环境,并部署到其中,以确保你的客户经历最小的停机时间。

其他措施 上述清单并不是保护 Kubernetes 集群的最全面选项。总会有新的漏洞被发现,最好的做法是假设总有一天你的集群会受到攻击。根本问题在于,攻击者只需要找到安全系统中的一个弱点,就能够闯入,而集群管理员需要确保所有资源中没有任何弱点,以实现完全的安全。因此,如果你计划成为一个集群管理员或者必须维护集群的安全性,那么在这个领域还有很多需要考虑的因素。然而,如果你是一个普通的开发者,那么上述步骤应该能帮助你编写安全的代码,无论你所在的组织规模如何。

(版权归原作者所有,侵删)


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
ChatGPT 团队是如何使用Kubernetes的Severe Flooding Continues to Rock Northeastern China深入理解Kubernetes Pod调试今年东京三月底的樱花「sealos」完成2000万元的天使轮和天使+轮融资,旨在打造以kubernetes为内核的云操作系统|早起看早期“互联网”要写成the Internet还是the internet?平心而论,目前在国内生活和办事挺方便通过例子介绍如何从零开发 Kubernetes OperatorKubernetes 1.27发布,冻结了原有的镜像注册中心并提供Pod资源就地更新功能3个管理多 Kubernetes 集群实用工具在 Kubernetes 集群中,如何正确选择工作节点资源大小这些 kubernetes 的安全机制你都了解吗?欧洲最美花园是啥样?凡尔赛花园如何利用 Kubernetes 实现应用零宕机#英语学习#Reserve, Preserve和Conserve有什么区别?看看你能答对这道题吗?973页kubernetes学习笔记,全是K8S核心干货,限时分享3天地中海邮轮行之一KSOC实验室发布首批Kubernetes材料清单(KBOMs)排障有用 | Docker 容器和 Kubernetes 退出码中文指南DevOps 是否已死?AI 和大语言模型给云计算和 DevOps 带来了哪些影响?|InfoQ 趋势报告973页kubernetes学习笔记,核心干货分享Kubernetes 网络排错终极指南Ziyi Zhang Dong-gun Jang Cecilia Cheung glenn close michael doug如何在 Kubernetes 集群上安装 Ansible AWX | Linux 中国如何快速查看 Kubernetes Pod 崩溃前的日志Pinterest 使用 Kubernetes 和 Helix 构建下一代异步计算平台 PacerKubernetes 如何保障容器可用性?一文介绍探针的使用Chinese Consumers Balk at Japan Wastewater Release分步指南:安装和访问 Kubernetes 仪表板 | Linux 中国Young Chinese Obsess Over MBTI, the American Personality TestDevSecOps,将安全性集成到软件开发的每一个阶段Hiring | Biotechnology Company Business Development Manager免费下载:技术人必看企业级Kubernetes战略方针如何在 Kubernetes 集群中设置动态 NFS 配置 | Linux 中国使用开源工具监控 Kubernetes 云成本 | Linux 中国
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。