热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

应该了解的10个Kubernetes安全上下文配置

在Kubernetes中安全地运行工作负载是很困难的,有很多配置都可能会影响到整个KubernetesAPI的安全性,这需要我们有大量的知识积累来正确的实施。Kubernetes在





在 Kubernetes 中安全地运行工作负载是很困难的,有很多配置都可能会影响到整个 Kubernetes API 的安全性,这需要我们有大量的知识积累来正确的实施。Kubernetes 在安全方面提供了一个强大的工具 securityContext
,每个 Pod 和容器清单都可以使用这个属性。在本文中我们将了解各种 securityContext
的配置,探讨它们的含义,以及我们应该如何使用它们。



securityContext
设置在 PodSpec
ContainerSpec
规范中都有定义,这里我们分别用 [P]
[C]
来表示。需要注意的是,如果一个设置在两个作用域中都可以使用和配置,那么我们应该优先考虑设置容器级别的。




1

runAsNonRoot [P/C]



我们知道容器是使用 namespaces 和 cgroups 来限制其进程,但只要在部署的时候做了一次错误的配置,就可以让这些进程访问主机上的资源。如果该进程以 root 身份运行,它对这些资源的访问权限与主机 root 账户是相同的。此外,如果其他 pod 或容器设置被用来减少约束(比如 procMount
capabilities
),拥有一个 root UID
就会提高风险,除非你有一个非常好的原因,否则你不应该以 root 身份运行一个容器。


那么,如果你有一个使用 root 的镜像需要部署,那应该怎么办呢?



1.1 使用基础镜像中提供的用户



通常情况下,基础镜像已经创建并提供了一个用户,例如,官方的 Node.js 镜像带有一个 UID 为 1000 的名为 node 的用户,我们就可以使用该身份来运行容器,但他们并没有在 Dockerfile
中明确地设置当前用户。我们可以在运行时用 runAsUser
设置来配置它,或者用自定义的 Dockerfile
来更改镜像中的当前用户。这里我们来看看使用自定义的 Dockerfile
来构建我们自己的镜像的例子。



在不深入了解镜像构建的情况下,让我们假设我们有一个预先构建好的 npm 应用程序。这里是一个最小的 Dockerfile 文件,用来构建一个基于 node:slim
的镜像,并以提供的 node 用户身份运行。


FROM node:slim
COPY --chown=node . /home/node/app/ # <--- Copy app into the home directory with right ownership
USER 1000 # <--- Switch active user to “node” (by UID)
WORKDIR /home/node/app # <--- Switch current directory to app
ENTRYPOINT ["npm", "start"] # <--- This will now exec as the “node” user instead of root


其中以 USER 开头的一行就是关键设置,这使得 node 成为从这个镜像启动的任何容器里面的默认用户。我们使用 UID 而不是用户的名字,因为 Kubernetes 无法在启动容器前将镜像的默认用户名映射到 UID 上,并且在部署时指定 runAsNotRoot: true
,会返回有关错误。



1.2 基础镜像没有提供用户


如果我们使用的基础镜像没有提供一个可以使用的用户,那么我们又应该怎么做呢?对于大部分进程来说,我们只需在自定义的 Dockerfile 中创建一个用户并使用它即可。如下所示:


FROM node:slim
RUN useradd somebody -u 10001 --create-home --user-group # <--- Create a user
COPY --chown=somebody . /home/somebody/app/
USER 10001
WORKDIR /home/somebody/app
ENTRYPOINT ["npm", "start"]


这里我们增加了一行创建用户的 RUN
命令即可。不过需要注意的是这对于 node.js
npm
来说,这很好用,但是其他工具可能需要文件系统的不同元素进行所有权变更。如果遇到任何问题,需要查阅对应工具的文档。




2

runAsUser/runAsGroup [P/C]



容器镜像可能有一个特定的用户或组,我们可以用 runAsUser
runAsGroup
来进行覆盖。通常,这些设置与包含具有相同所有权 ID 的文件的卷挂载结合在一起。


....
spec:
containers:
- name: web
image: mycorp/webapp:1.2.3
securityContext:
runAsNonRoot: true
runAsUser: 10001
....


不过使用这些配置也是有风险的,因为你为容器做出的运行时决定可能与原始镜像不兼容。例如, jenkins/jenkins
镜像以名为 jenkins:jenkins
组:用户
身份运行,其应用文件全部由该用户拥有。如果我们配置一个不同的用户,它将无法启动,因为该用户不存在于镜像的 /etc/passwd
文件中。即使它以某种方式存在,它也很可能在读写 jenkins:jenkins
拥有的文件时出现问题。我们可以用一个简单的 docker 运行命令来验证这个问题。


$ docker run --rm -it -u eric:eric jenkins/jenkins
docker: Error response from daemon: unable to find user eric: no matching entries in passwd file.


上面我们提到确保容器进程不以 root 用户身份运行是一个非常好的主意,但不要依赖 runAsUser
runAsGroup
设置来保证这一点,未来有人可能会删除这些配置,请确保同时将 runAsNonRoot
设置为 true。




3

seLinuxOptions [P/C]



SELinux
是一个用于控制对 Linux 系统上的应用、进程和文件进行访问的策略驱动系统,它在 Linux 内核中实现了 Linux 安全模块框架。SELinux 是基于标签的策略,它将一些标签应用于系统中的所有元素,然后将元素进行分组。这些标签被称为 安全上下文
(不要和 Kubernetes 中的 securityContext
混淆了)- 由用户、角色、类型和可选的一些其他属性组成,格式为: user:role:type:level



然后,SELinux 使用策略来定义特定上下文中的哪些进程可以访问系统中其他被标记的对象。SELinux 可以是严格执行 enforced
模式,在这种情况下,访问将被拒绝,如果被配置为允许的 permissive
模式,那么安全策略没有被强制执行,当安全策略规则应该拒绝访问时,访问仍然被允许,然而,此时会向日志文件发送一条消息,表示该访问应该被拒绝。在容器中,SELinux 通常给容器进程和容器镜像打上标签,以限制该进程只能访问镜像中的文件。



默认的 SELinux 策略将在实例化容器时由容器运行时应用, securityContext
中的 seLinuxOptions
允许配置自定义的 SELinux 策略标签,请注意,改变容器的 SELinux 策略标签有可能允许容器进程摆脱容器镜像并访问主机文件系统。


当然只有当宿主机操作系统支持 SELinux 时,这个功能才会起作用。




4

seccompProfile [P/C]



Seccomp
表示一种安全计算模式,是 Linux 内核的一项功能,它可以限制一个特定进程从用户空间到内核的调用。seccomp 配置文件是使用一个 JSON 文件进行定义的,通常由一组系统调用和发生这些系统调用时的默认动作组成。如下配置所示:


{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
"name": "accept",
"action": "SCMP_ACT_ALLOW",
"args": []
},
{
"name": "accept4",
"action": "SCMP_ACT_ALLOW",
"args": []
},
...
]
}


Kubernetes 通过在 securityContext
中的 seccompProfile
属性来提供一个使用自定义配置文件的机制。


seccompProfile:
type: Localhost
localhostProfile: profiles/myprofile.json


这里配置的 type
字段有三个可选的值:




  • Localhost
    localhostProfile
    seccomp




  • Unconfined
    :其中没有配置文件。




  • RuntimeDefault
    :其中使用容器运行时的默认值--如果没有指定类型,就是默认值。




我们可以在 PodSecurityContext
securityContext
中使用这些配置,如果两者都配置了,就会使用容器级别中的配置。



此外与大多数安全相关的设置一样, 最小权限原则
在此同样适用。只给你的容器访问它所需要的权限即可。首先创建一个配置文件,简单地记录哪些系统调用正在发生,然后测试你的应用程序,建立一套允许的系统调用规则。我们可以在 Kubernetes 教程( https://kubernetes.io/docs/tutorials/clusters/seccomp
)中找到关于 Seccomp
的更多信息。




5

避免使用特权容器 [C]



给容器授予特权模式是非常危险的,一般会有一种更简单的方式来实现特定的权限,或者可以通过授予 Linux Capabilities
权限来控制。容器运行时控制器着特权模式的具体实现,但是它会授予容器所有的特权,并解除由 cgroup 控制器执行的限制,它还可以修改 Linux 安全模块的配置,并允许容器内的进程逃离容器。



容器在宿主机中提供了进程隔离,所以即使容器是使用 root 身份运行的,也有容器运行时不授予容器的 Capabilities
。如果配置了特权模式,容器运行时就会授予系统 root 的所有能力,从安全角度来看,这是很危险的,因为它允许对底层宿主机系统的所有操作访问。



避免使用特权模式,如果你的容器确实需要额外的能力,只需通过添加 capabilities
来满足你的需求。除非你的容器需要控制主机内核中的系统级设置,如访问特定的硬件或重新配置网络,并且需要访问主机文件系统,那么它就不需要特权模式。




6

Linux Capabilities [C]



Capabilities
是一个内核级别的权限,它允许对内核调用权限进行更细粒度的控制,而不是简单地以 root 身份运行。 Capabilities
包括更改文件权限、控制网络子系统和执行系统管理等功能。在 securityContext
中,Kubernetes 可以添加或删除 Capabilities
,单个 Capabilities
或逗号分隔的列表可以作为一个字符串数组进行配置。另外,我们也可以使用 all
来添加或删除所有的配置。这种配置会被传递给容器运行时,在它创建容器的时候会配置上 Capabilities
集合,如果 securityContext
中没有配置,那么容器将会直接容器运行时提供的所有默认配置。


securityContext:
capabilities:
drop:
- all
add: ["MKNOD"]


一般推荐的做法是先删除所有的配置,然后只添加你的应用程序实际需要的,在大部分情况下,应用程序在正常运行中实际上不需要任何 Capabilities
,通过删除所有配置来测试,并通过监控审计日志来调试问题,看看哪些功能被阻止了。



请注意,当在 securityContext
中列出要放弃或添加的 Capabilities
时,你要删除内核在命名 Capabilities
时使用的 CAP_
前缀。 capsh
工具可以给我们一个比较友好的调试信息,可以来说明你的容器中到底启用了哪些 Capabilities
,当然不要在生产容器中使用这个工具,因为这使得攻击者很容易弄清楚哪些 Capabilities
被启用了。




7

以只读文件系统运行 [C]


如果你的容器被入侵,而且它有一个可读写的文件系统,那么攻击者就可以随意地改变它的配置、安装软件,并有可能启动其他的漏洞。拥有一个只读的文件系统有助于防止这些类型的安全问题,因为它限制了攻击者可以执行的操作。一般来说,容器不应该要求对容器文件系统进行写入,如果你的应用程序是有状态数据,那么你应该使用外部持久化方法,如数据库、volume 或其他一些服务。另外,确保所有的日志都写到 stdout 或日志转发器上。




8

procMount [C]



默认情况下,为了防止潜在的安全问题,容器运行时会屏蔽容器内 /proc
文件系统的某些部分文件。然而有时需要访问 /proc
的这些文件,特别是在使用嵌套容器时,因为它经常被用作集群内构建过程的一部分。该配置只有两个有效的选项:





  • Default
    :保持标准的容器运行时行为




  • Unmasked
    :它删除 /proc
    文件系统的所有屏蔽行为




显然只有当我们知道在做什么的时候才应该使用这个配置,如果你是为了构建镜像而使用它,请检查构建工具的最新版本,因为许多工具不再需要这个设置了,最好升级下工具并设置为 Default
默认的 procMount




9

fsGroup/fsGroupChangePolicy [P]



fsGroup
设置定义了一个组,当卷被 pod 挂载时,Kubernetes 将把卷中所有文件的权限改为该组。这里的行为也由 fsGroupChangePolicy
控制,它可以被设置为 onRootMismatch
Always
。如果设置为 onRootMismatch
则只有当权限与容器 root 的权限不匹配时才会被改变。



不过在使用 fsGroup
时也要慎重,改变整个 volume 卷的组所有权会导致 变慢
,如果是大型文件系统 启动也会延迟
。如果共享同一卷的其他进程没有对新的 GID 的访问权限,它也会对这些进程造成损害。由于这个原因,一些共享文件系统如 NFS,没有实现这个功能。这些设置也不影响临时的 ephemeral 卷。




10

sysctls [P]



Sysctls
是 Linux 内核的一个功能,它允许管理员修改内核配置。在一个完整的 Linux 操作系统中,这些是通过使用 /etc/sysctl.conf
定义的,也可以使用 sysctl
工具进行修改。



securityContext
中的 sysctls
配置允许在容器中修改特定的 sysctls
。只有一小部分的 sysctls
可以在每个容器的基础上进行修改,它们都在内核中被命名的。在这个可以配置的子集中,有些被认为是安全的,而更多的则被认为是不安全的,这取决于对其他 pod 的潜在影响。在集群中,不安全的 sysctls
通常是被禁用,需要由集群管理员专门开启。



鉴于有可能破坏底层操作系统的稳定,除非你有非常特殊的要求,否则应该避免通过 sysctls
修改内核参数。




11

总结



在用 securityContext
加固你的应用时,有很多事情需要注意。如果使用得当,它们是一种非常有效的工具,我们希望这个列表能帮助你的团队为你的工作负载和环境进行正确的安全配置。


原文链接:https://snyk.io/blog/10-kubernetes-security-context-settings-you-should-understand/








推荐阅读
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 前言:原本纠结于Web模板,选了Handlebars。后来发现页面都是弱逻辑的,不支持复杂逻辑表达式。几乎要放弃之际,想起了Javascript中ev ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • mysql-cluster集群sql节点高可用keepalived的故障处理过程
    本文描述了mysql-cluster集群sql节点高可用keepalived的故障处理过程,包括故障发生时间、故障描述、故障分析等内容。根据keepalived的日志分析,发现bogus VRRP packet received on eth0 !!!等错误信息,进而导致vip地址失效,使得mysql-cluster的api无法访问。针对这个问题,本文提供了相应的解决方案。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 背景应用安全领域,各类攻击长久以来都危害着互联网上的应用,在web应用安全风险中,各类注入、跨站等攻击仍然占据着较前的位置。WAF(Web应用防火墙)正是为防御和阻断这类攻击而存在 ... [详细]
  • 本文介绍了如何在Azure应用服务实例上获取.NetCore 3.0+的支持。作者分享了自己在将代码升级为使用.NET Core 3.0时遇到的问题,并提供了解决方法。文章还介绍了在部署过程中使用Kudu构建的方法,并指出了可能出现的错误。此外,还介绍了开发者应用服务计划和免费产品应用服务计划在不同地区的运行情况。最后,文章指出了当前的.NET SDK不支持目标为.NET Core 3.0的问题,并提供了解决方案。 ... [详细]
  • 本文概述了JNI的原理以及常用方法。JNI提供了一种Java字节码调用C/C++的解决方案,但引用类型不能直接在Native层使用,需要进行类型转化。多维数组(包括二维数组)都是引用类型,需要使用jobjectArray类型来存取其值。此外,由于Java支持函数重载,根据函数名无法找到对应的JNI函数,因此介绍了JNI函数签名信息的解决方案。 ... [详细]
  • 如何使用PLEX播放组播、抓取信号源以及设置路由器
    本文介绍了如何使用PLEX播放组播、抓取信号源以及设置路由器。通过使用xTeve软件和M3U源,用户可以在PLEX上实现直播功能,并且可以自动匹配EPG信息和定时录制节目。同时,本文还提供了从华为itv盒子提取组播地址的方法以及如何在ASUS固件路由器上设置IPTV。在使用PLEX之前,建议先使用VLC测试是否可以正常播放UDPXY转发的iptv流。最后,本文还介绍了docker版xTeve的设置方法。 ... [详细]
  • 目录1、将mysql数据导出到SQL文件中(数据库存在的情况)2、将现有的sql文件数据导入到数据库中(前提数据库存在) 3、利用Navicat导出SQL文件和导入SQL文件1)从 ... [详细]
  • 前言:原本纠结于Web 模板,选了Handlebars。后来发现页面都是弱逻辑的,不支持复杂逻辑表达式。几乎要放弃之际,想起了Javascript中eval函数。虽然eval函 ... [详细]
author-avatar
mobiledu2502937981
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有