cks详细学习笔记
2024-04-09 11:11:23 1 举报
AI智能生成
登录查看完整内容
CKS考试完全实操,需要动手!需要动手!需要动手!
作者其他创作
大纲/内容
在节点上加载一个存在漏洞的内核模块,然后观察pod中的变化,一旦宿主机被通过pcspkr模块工具,也会影响到容器查看加载模块个数: lsmod | wc -l加载模块:modprobe pcspkr删除模块:modprobe -r pcspkr
去除多余的系统模块
系统模块
最小特权原则 (Principle of least privilege,POLP) :是一种信息安全概念,即为用户提供执行其工作职责所需的最小权限等级或许可。
• 减少网络攻击面:当今,大多数高级攻击都依赖于利用特权凭证。通过限制超级用户和管理员权限,最小权限执行有助于减少总体网络攻击面。• 阻止恶意软件的传播: 通过在服务器或者在应用系统上执行最小权限,恶意软件攻击(例如SQL注入攻击)将很难提权来增加访问权限并横向移动破坏其他软件、设备。• 有助于简化合规性和审核:许多内部政策和法规要求都要求组织对特权帐户实施最小权限原则,以防止对关键业务系统的恶意破坏。最小权限执行可以帮助组织证明对特权活动的完整审核跟踪的合规性。
最小特权原则 (POLP) 重要性
• 在所有服务器、业务系统中,审核整个环境以查找特权帐户(例如SSH账号、管理后台账号、跳板机账号);• 减少不必要的管理员权限,并确保所有用户和工具执行工作时所需的权限;• 定期更改管理员账号密码;• 监控管理员账号操作行为,告警通知异常活动。将管理员帐户与标准帐户分开,并隔离特权用户会话。将特权管理员帐户凭据提供给数字保管库,以开始保护和管理这些帐户。启用即时访问特权升级,允许用户根据需要临时访问特权帐户或运行特权命令。
在团队中实施最小特权原则 (POLP)
最小特权原则
AppArmor(Application Armor) 是一个 Linux 内核安全模块,可用于限制主机操作系统上运行的进程的功能。每个进程都可以拥有自己的安全配置文件。安全配置文件用来允许或禁止特定功能,例如网络访问、文件读/写/执行权限等。Linux发行版内置:Ubuntu、Debian
• Enforcement(强制模式) :在这种模式下,配置文件里列出的限制条件都会得到执行,并且对于违反这些限制条件的程序会进行日志记录。• Complain(投诉模式):在这种模式下,配置文件里的限制条件不会得到执行,Apparmor只是对程序的行为进行记录。一般用于调试。
Apparmor两种工作模式
• aa-enabled:查看apparmor是否开启- apparmor_status:查看AppArmor配置文件的当前状态的• apparmor_parser:将AppArmor配置文件加载到内核中 apparmor_parser <profile># 加载到内核中apparmor_parser -r <profile># 重新加载配置apparmor_parser -R <profile># 删除配置• aa-complain:将AppArmor配置文件设置为投诉模式,需要安装apparmor-utils软件包• aa-enforce:将AppArmor配置文件设置为强制模式,需要安装apparmor-utils软件包
常用命令
• K8s版本v1.4+,检查是否支持:kubectl describe node |grep AppArmor• Linux内核已启用AppArmor,查看 cat /sys/module/apparmor/parameters/enabled• 容器运行时需要支持AppArmor,目前Docker已支持
K8s使用AppArmor的先决条件
apiVersion: v1kind: Podmetadata: name: hello-apparmor annotations: container.apparmor.security.beta.kubernetes.io/<container_name>: localhost/<profile_ref>...• <container_name> Pod中容器名称• <profile_ref> Pod所在宿主机上策略名,默认目录/etc/apparmor.d
在注解中指定AppArmor策略配置文件
工作流程
步骤:1、将自定义策略配置文件保存到/etc/apparmor.d/2、加载配置文件到内核:apparmor_parser <profile>3、Pod注解指定策略配置名
| 字符 | 描述 || ---- | ---- ||r| 读| w 写 a 追加k 文件锁定l 链接x 可执行
访问文件权限模式
|通配符|描述 |示例|* | 在目录级别匹配零个或多个字符|/dir/* 匹配目录中的任何文件/dir/a* 匹配目录中以a开头的任意文件/dir/*.png 匹配目录中以.png结尾的任意文件/dir/a*/ 匹配/dir里面以a开头的目录/dir/*a/ 匹配/dir里面以a结尾的目录** | 在多个目录级别匹配零个或多个字符|/dir/** 匹配/dir目录或者/dir目录下任何文件和目录/dir/**/ 匹配/dir或者/dir下面任何目录[]、[^] | 字符串,匹配其中任意字符 |/dir/[^.]* 匹配/dir目录中以.之外的任何文件/dir/**[^/] 匹配/dir目录或者/dir下面的任何目录中的任何文件
匹配目录和文件
apiVersion: v1kind: Podmetadata: name: hello-apparmor annotations: container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-deny-writespec: containers: - name: hello image: busybox command: [ \"sh\
进容器进行测试kubectl exec hello-apparmor -- cat /proc/1/attr/currentk8s-apparmor-deny-write (enforce)kubectl exec hello-apparmor -- touch testtouch: test: Permission deniedcommand terminated with exit code 1
案例:容器文件系统访问限制
AppArmor限制容器对资源访问
调用关系图
对于 Linux 来说,用户层一切资源相关操作都需要通过系统调用来完成;系统调用实现技术层次上解耦,内核只关心系统调用API的实现,而不必关心谁调用的。
seccomp是linux kernel从2.6.23版本开始所支持的一种安全机制。在Linux系统里,大量的系统调用(systemcall)直接暴露给用户态程序。strace -fqc来查看命令背后会调用大量的syscall
Seccomp(Secure computing mode) 是一个 Linux 内核安全模块,可用于应用进程允许使用的系统调用。容器实际上是宿主机上运行的一个进程,共享宿主机内核,如果所有容器都具有任何系统调用的能力,那么容器如果被入侵,就很轻松绕过容器隔离更改宿主机系统权限或者进入宿主机。这就可以使用Seccomp机制限制容器系统调用,有效减少攻击面。Linux发行版内置:CentOS、Ubuntu
SCMP_ACT_KILL:当进程进行对应的系统调用时,内核发出SIGSYS信号终止该进程,该进程不会接受到这个信号SCMP_ACT_TRAP:当进程进行对应的系统调用时,该进程会接收到SIGSYS信号,并改变自身行为SCMP_ACT_ERRNO:当进程进行对应的系统调用时,系统调用失败,进程会接收到errno返回值SCMP_ACT_TRACE:当进程进行对应的系统调用时,进程会被跟踪SCMP_ACT_ALLOW:允许进程进行对应的系统调用行为SCMP_ACT_LOG:记录所有信息,/var/log/syslog
seccomp所包含的动作
1.19版本之前annotations: seccomp.security.alpha.kubernetes.io/pod: \"localhost/<profile>\"或者我们设置到容器范围:annotations: container.security.alpha.kubernetes.io/<container-name>: \"localhost/profile.json\"
seccompProfile.type:Unconfined - 如果没有其他选择,Seccomp不会应用于容器进程(这是Kubernetes中的默认设置)。RuntimeDefault - 使用默认的容器运行时配置文件。Localhost - 指定自定有的profile文件。当type 为该值时,此时必须指定localhostProfile字段的值。
1.19版本+apiVersion: v1kind: Podmetadata: name: hello-seccompspec: securityContext: seccompProfile: type: Localhost localhostProfile: <profile> # Pod所在宿主机上策略文件名,默认目录:/var/lib/kubelet/seccomp;默认目录的相对路径 containers:...
Seccomp在Kubernetes 1.3版本引入,在1.19版本成为GA版本,因此K8s中使用Seccomp可以通过以下两种方式
seccomp基本配置文件包括三个元素:defaultAction:在syscalls部分未定义的任何系统调用默认动作为允许syscalls names 系统调用名称,可以换行写多个 SCMP_ACT_ERRNO 阻止系统调用
mkdir /var/lib/kubelet/seccompvi /var/lib/kubelet/seccomp/chmod.json{ \"defaultAction\": \"SCMP_ACT_ALLOW\
示例:禁止容器使用chmod
ps -ef |grep dockerdcat /etc/docker/seccomp.json
docker每个容器默认都设置了一个seccomp profiledocker会将seccomp传递给runc中的sepc.linux.seccomp。可以通过—security-opt seccomp=xxx来设置docker的seccomp策略,xxx为json格式的文件,其中定义了seccomp规则。也可以通过--security-opt seccomp=unconfined来关闭docker引入默认的seccomp规则的限制。
大多数容器运行时都提供一组允许或不允许的默认系统调用。通过使用 runtime/default 注释 或将Pod 或容器的安全上下文中的 seccomp 类型设置为 RuntimeDefault,可以轻松地在 Kubernetes中应用默认值。Docker默认配置说明:https://docs.docker.com/engine/security/seccomp/
Seccomp 限制容器进程系统调用
Sysdig:一个非常强大的系统监控、分析和故障排查工具。汇聚 strace+tcpdump+htop+iftop+lsof 工具功能于一身!sysdig 除了能获取系统资源利用率、进程、网络连接、系统调用等信息,还具备了很强的分析能力,例如:• 按照CPU使用率对进程排序• 按照数据包对进程排序• 打开最多的文件描述符进程• 查看进程打开了哪些文件• 查看进程的HTTP请求报文• 查看机器上容器列表及资源使用情况
sysdig 通过在内核的驱动模块注册系统调用的 hook,这样当有系统调用发生和完成的时候,它会把系统调用信息拷贝到特定的buffer,然后用户态组件对数据信息处理(解压、解析、过滤等),并最终通过 sysdig 命令行和用户进行交互。
sysdig
rpm --import https://s3.amazonaws.com/download.draios.com/DRAIOS-GPG-KEY.public curl -s -o /etc/yum.repos.d/draios.repo https://s3.amazonaws.com/download.draios.com/stable/rpm/draios.repoyum install epel-release -yyum install sysdig -y /usr/bin/sysdig-probe-loader # 加载驱动模块
安装sysdig
sysdig常用参数
执行sysdig命令,实时输出大量系统调用。示例:59509 23:59:19.023099531 0 kubelet (1738) < epoll_ctl格式:%evt.num %evt.outputtime %evt.cpu %proc.name (%thread.tid) %evt.dir %evt.type %evt.info• evt.num: 递增的事件号• evt.time: 事件发生的时间• evt.cpu: 事件被捕获时所在的 CPU,也就是系统调用是在哪个 CPU 执行的• proc.name: 生成事件的进程名字• thread.tid: 线程的 id,如果是单线程的程序,这也是进程的 pid• evt.dir: 事件的方向(direction),> 代表进入事件,< 代表退出事件• evt.type: 事件的名称,比如 open、stat等,一般是系统调用• evt.args: 事件的参数。如果是系统调用,这些对应着系统调用的参数自定义格式输出:sysdig -p \"user:%user.name time:%evt.time proc_name:%proc.name\"
sysdig输出格式
• fd:根据文件描述符过滤,比如 fd 标号(fd.num)、fd 名字(fd.name) • process:根据进程信息过滤,比如进程 id(proc.id)、进程名(proc.name) • evt:根据事件信息过滤,比如事件编号、事件名• user:根据用户信息过滤,比如用户 id、用户名、用户 home 目录• syslog:根据系统日志过滤,比如日志的严重程度、日志的内容• container:根据容器信息过滤,比如容器ID、容器名称、容器镜像查看完整过滤器列表:sysdig -l
sysdig过滤
1、查看一个进程的系统调用sysdig proc.name=kubelet2、查看建立TCP连接的事件sysdig evt.type=accept3、查看/etc目录下打开的文件描述符sysdig fd.name contains /etc4、查看容器的系统调用sysdig -M 10 container.name=web注:还支持运算操作符,=、!=、>=、>、<、<=、contains、in 、exists、and、or、not
示例
Chisels:实用的工具箱,一组预定义的功能集合,用来分析特定的场景。sysdig –cl 列出所有Chisels,以下是一些常用的:• topprocs_cpu:输出按照 CPU 使用率排序的进程列表,例如sysdig -c • topprocs_net:输出进程使用网络TOP• topprocs_file:进程读写磁盘文件TOP• topfiles_bytes:读写磁盘文件TOP• netstat:列出网络的连接情况
网络# 查看使用网络的进程TOPsysdig -c topprocs_net# 查看建立连接的端口sysdig -c fdcount_by fd.sport \"evt.type=accept\" -M 10# 查看建立连接的端口sysdig -c fdbytes_by fd.sport# 查看建立连接的IPsysdig -c fdcount_by fd.cip \"evt.type=accept\" -M 10# 查看建立连接的IPsysdig -c fdbytes_by fd.cip硬盘# 查看进程磁盘I/O读写sysdig -c topprocs_file# 查看进程打开的文件描述符数量sysdig -c fdcount_by proc.name \"fd.type=file\" -M 10# 查看读写磁盘文件sysdig -c topfiles_bytessysdig -c topfiles_bytes proc.name=etcd# 查看/tmp目录读写磁盘活动文件sysdig -c fdbytes_by fd.filename \"fd.directory=/tmp/\"CPU# 查看CPU使用率TOPsysdig -c topprocs_cpu# 查看容器CPU使用率TOPsysdig -pc -c topprocs_cpu container.name=websysdig -pc -c topprocs_cpu container.id=web容器# 查看机器上容器列表及资源使用情况csysdig –vcontainers# 查看容器资源使用TOPsysdig -c topcontainers_cpu/topcontainers_net/topcontainers_file
Chisels
分析容器系统调用:Sysdig
3、k8s容器运行环境安全加固
安全上下文(Security Context):K8s对Pod和容器提供的安全机制,可以设置Pod特权和访问控制。
• 自主访问控制(Discretionary Access Control):基于用户ID(UID)和组ID(GID),来判定对对象(例如文件)的访问权限。• 安全性增强的 Linux(SELinux): 为对象赋予安全性标签。• 以特权模式或者非特权模式运行。• Linux Capabilities: 为进程赋予 root 用户的部分特权而非全部特权。• AppArmor:定义Pod使用AppArmor限制容器对资源访问限制• Seccomp:定义Pod使用Seccomp限制容器进程的系统调用• AllowPrivilegeEscalation: 禁止容器中进程(通过 SetUID 或 SetGID 文件模式)获得特权提升。当容器以特权模式运行或者具有CAP_SYS_ADMIN能力时,AllowPrivilegeEscalation总为True。 • readOnlyRootFilesystem:以只读方式加载容器的根文件系统。
安全上下文限制维度
容器中的应用程序默认以root账号运行的,这个root与宿主机root账号是相同的,拥有大部分对Linux内核的系统调用权限,这样是不安全的,所以我们应该将容器以普通用户运行,减少应用程序对权限的使用。可以通过两种方法设置普通用户:• Dockerfile里使用USER指定运行用户• K8s里指定spec.securityContext.runAsUser,指定容器默认用户UIDspec: securityContext: runAsUser: 1000 # 镜像里必须有这个用户UID fsGroup: 1000 # 数据卷挂载后的目录属组设置为该组 containers: - image: lizhenliang/flask-demo:root name: web securityContext: allowPrivilegeEscalation: false # 不允许提权
设置容器以普通用户运行
Capabilities 是一个内核级别的权限,它允许对内核调用权限进行更细粒度的控制,而不是简单地以 root 身份能力授权。Capabilities 包括更改文件权限、控制网络子系统和执行系统管理等功能。在securityContext 中,可以添加或删除 Capabilities,做到容器精细化权限控制。
容器默认没有挂载文件系统能力,添加SYS_ADMIN增加这个能力apiVersion: v1kind: Podmetadata: name: cap-pod spec: containers: - image: busybox name: test command: - sleep - 24h securityContext: capabilities: add: [\"SYS_ADMIN\"]
Linux Capabilities:
容器中有些应用程序可能需要访问宿主机设备、修改内核等需求,在默认情况下,容器没这个有这个能力,因此这时会考虑给容器设置特权模式。启用特权模式:containers:- image: lizhenliang/flask-demo:root name: web securityContext: privileged: true启用特权模式就意味着,你要为容器提供了访问Linux内核的所有能力,这是很危险的,为了减少系统调用的供给,可以使用Capabilities为容器赋予仅所需的能力。
避免使用特权容器
只读挂载容器文件系统,防止恶意二进制文件创建apiVersion: v1kind: Podmetadata: name: cap-podspec: containers: - image: busybox name: test command: - sleep - 24h securityContext: readOnlyRootFilesystem: true
Pod安全上下文
PodSecurityPolicy(简称PSP):Kubernetes中Pod部署时重要的安全校验手段,能够有效地约束应用运行时行为安全。使用PSP对象定义一组Pod在运行时必须遵循的条件及相关字段的默认值,只有Pod满足这些条件才会被K8s接受。
Pod 安全策略(Pod Security Policy)是集群级别的资源(默认不属于任何Namespace,但也可以在创建PSP规则时指定绑定到具体的Namespace),它能够控制Pod的各个安全方面。
|配置项 |描述|privileged 启动特权容器。hostPID,hostIPC 使用主机namespaces。hostNetwork,hostPorts 使用主机网络和端口。volumes 允许使用的挂载卷类型。allowedHostPaths 允许hostPath类型挂载卷在主机上挂载的路径,通过pathPrefix字段声明允许挂载的主机路径前缀组。allowedFlexVolumes 允许使用的指定FlexVolume驱动。fsGroup 配置Pod中挂载卷使用的辅组ID。readOnlyRootFilesystem 约束启动Pod使用只读的root文件系统。runAsUser,runAsGroup,supplementalGroups 指定Pod中容器启动的用户ID以及主组和辅组ID。allowPrivilegeEscalation,defaultAllowPrivilegeEscalation 约束Pod中是否允许配置allowPrivilegeEscalation=true,该配置会控制setuid的使用,同时控制程序是否可以使用额外的特权系统调用。defaultAddCapabilities,requiredDropCapabilities,allowedCapabilities 控制Pod中使用的Linux Capabilities。seLinux 控制Pod使用seLinux配置。allowedProcMountTypes 控制Pod允许使用的ProcMountTypes。annotations 配置Pod中容器使用的AppArmor或seccomp。forbiddenSysctls,allowedUnsafeSysctls 控制Pod中容器使用的sysctl配置。
Pod安全策略限制维度
PSP准入控制器
无论是通过user account还是service account(例如Deployment控制器会使用)创建pod,请求都会通过准入控制器。如果我们在准入控制器处开启了PSP,并没有设置任何的规则,那么K8s账号(包括admin)发送的请求都会被拒绝。当我们创建了PSP规则,那么K8s账号发送的请求必须在满足PSP的规则后才能够对Pod进行操作,否则请求依旧会被拒绝。如果我们没有给自己创建的User Account或者Service Account赋予访问对应PSP的权限,用户发送的操作请求是无法到达PSP的,那么请求将被拒绝;由于默认的K8s admin的账号拥有着所有的权限,所以可以访问集群中所有的PSP。
PSP准入控制器工作流程
1、用户有创建pod的授权2、用户能访问PSP策略3、PSP策略允许创建pod
开启PSP后创建pod的条件
# 创建psp策略,创建之后admin用户就可以创建pod了,但是不能创建特权podapiVersion: policy/v1beta1kind: PodSecurityPolicymetadata: name: deny-privilegespec: privileged: false # 不允许特权Pod# 下面是一些必要的字段 seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: RunAsAny fsGroup: rule: RunAsAny volumes: - '*'
hhf用户创建特权pod失败# kubectl run test --image=nginx --kubeconfig=/root/cert/hhf-config --privileged=trueError from server (Forbidden): pods \"test\" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
禁止创建特权模式的Pod
使用K8s的user调动Deployment控制器或者其他控制器部署pod时。而这些控制器在收到了我们的请求后,也会利用自己的Service Accounts完成后续操作。如果Deployment控制器的SA没有被赋予访问运行Deployment操作的PSP规则的权限,就算我们使用admin这个默认的账号也无法完成Deployment的操作。能创建deployment,但是pod没有部署
# 创建clusterrolekubectl create clusterrole psp-deny-privilege --verb=use --resource=podsecuritypolicies --resource-name=deny-privilege# 给Deployment控制器的SA授权去访问PSP(pod依然没有部署,需要给replicaset控制器的SA授权)kubectl create clusterrolebinding crolebinding-deny-privilege --clusterrole=psp-deny-privilege --serviceaccount=kube-system:deployment-controller# 给replicaset控制器的SA授权去访问PSPkubectl create clusterrolebinding crolebinding-deny-privilege2 --clusterrole=psp-deny-privilege --serviceaccount=kube-system:replicaset-controller或者直接给Kube-system命名空间内所有的SA做绑定kubectl create clusterrolebinding crolebinding-deny-privilege3 --clusterrole=psp-deny-privilege --serviceaccount=kube-system:replicaset-controller
使用Deployment部署pod
apiVersion: policy/v1beta1kind: PodSecurityPolicymetadata: name: non-rootspec: privileged: false # 不允许特权Pod # 下面是一些必要的字段 seLinux: rule: RunAsAny supplementalGroups: rule: RunAsAny runAsUser: rule: MustRunAsNonRoot fsGroup: rule: RunAsAny volumes: - '*'
禁止没指定普通用户运行的容器(runAsUser)
Pod安全策略(PSP)
OPA(Open Policy Agent):是一个开源的、通用策略引擎,可以将策略编写为代码。提供一个种高级声明性语言-Rego来编写策略,并把决策这一步骤从复杂的业务逻辑中解耦出来。OPA可以用来做什么?• 拒绝不符合条件的YAML部署• 允许使用哪些仓库中的镜像• 允许在哪个时间段访问系统• 等...
OPA 为我们提供了 REST API,我们的系统可以调用这些 API 来检查请求负载是否满足策略。任何需要做出授权或策略决策的服务都可以调用(策略查询),然后 OPA 可以根据策略的 Rego 代码做出决策,并将决策返回给相应地进一步处理请求的服务. 执行由实际服务本身完成,OPA 只负责做出决定。
OPA概述
创建OPA空规则mkdir -p /etc/docker/policiesvim /etc/docker/policies/authz.regopackage docker.authzallow = true
安装OPA插件docker plugin install openpolicyagent/opa-docker-authz-v2:0.8 opa-args=\"-policy-file /opa/policies/authz.rego\"安装插件并制定策略的位置。容器内的/opa/policies/authz.rego就等于宿主机的/etc/docker/policies/authz.rego,因为opa插件做了卷挂载。
配置 Docker 守护程序以使用插件进行授权cat > /etc/docker/daemon.json <<EOF{ \"authorization-plugins\": [\"openpolicyagent/opa-docker-authz-v2:0.8\"]}EOF通知 Docker 守护进程重新加载配置文件:kill -HUP $(pidof dockerd)
编写OPA规则,修改authz.rego文件package docker.authzdefault allow = falseallow { not deny}deny { seccomp_unconfined}seccomp_unconfined { # This expression asserts that the string on the right-hand side is equal # to an element in the array SecurityOpt referenced on the left-hand side. input.Body.HostConfig.SecurityOpt[_] == \"seccomp:unconfined\"}default allow表示默认是拒绝所有;deny {xxx} 表示拒绝xxx规则所定义的操作;allow {not deny}则表示除了deny {xxx} 拒绝的,其他都允许input.Body是固定的HostConfig.SecurityOpt是docker inspect 查看到的
验证OPA规则是否生效docker run -d --restart=always --name=web1 --security-opt seccomp:unconfined nginxdocker: Error response from daemon: authorization denied by plugin openpolicyagent/opa-docker-authz-v2:0.8: request rejected by administrative policy.See 'docker run --help'.
在Docker中使用OPA
Gatekeeper 是基于OPA的一个Kubernetes 策略解决方案,可替代PSP或者部分RBAC功能。当在集群中部署了Gatekeeper组件,APIServer所有的创建、更新或者删除操作都会触发Gatekeeper来处理,如果不满足策略则拒绝。
Gatekeeper 项目是 OPA 的 Kubernetes 特定实现。Gatekeeper 允许我们以 Kubernetes 原生方式使用 OPA 来执行所需的策略。在 Kubernetes 集群上,Gatekeeper 作为ValidatingAdmissionWebhook安装。
在请求通过 K8s API 服务器的身份验证和授权之后,但在它们持久化到数据库中之前,准入控制器可以拦截请求。如果任何准入控制器拒绝请求,则拒绝整个请求。准入控制器的局限性在于它们需要编译到 kube-apiserver 中,并且只有在 apiserver 启动时才能启用。
部署Gatekeeper:kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.7/deploy/gatekeeper.yaml
•Template:策略逻辑实现的地方,使用rego语言•Contsraint:负责Kubernetes资源对象的过滤或者为Template提供输入参数
Gatekeeper的策略由两个资源对象组成:
Gatekeeper 使用 OPA 约束框架来描述和执行策略,在定义约束之前必须首先定义一个 ConstraintTemplate 对象,它描述了强制执行约束的 Rego 和约束的模式。约束的模式允许管理员对约束的行为进行微调,就像函数的参数一样。
在K8s集群中使用OPA
约束:apiVersion: constraints.gatekeeper.sh/v1beta1kind: BlacklistImagesmetadata: generation: 1 managedFields: name: pod-trusted-images resourceVersion: \"14449\"spec: match: kinds: - apiGroups: - \"\" kinds: - Pod
验证OPA规则是否生效:# 打tagctr i tag docker.io/library/busybox:latest xx.163.com/busybox:v1# 尝试使用该镜像创建podkubectl run test --image=xx.163.com/busybox:v1Error from server ([pod-trusted-images] not trusted image!): admission webhook \"validation.gatekeeper.sh\" denied the request: [pod-trusted-images] not trusted image!
禁止xx.163.com开头的镜像
约束模板:apiVersion: templates.gatekeeper.sh/v1beta1kind: ConstraintTemplatemetadata: name: privileged spec: crd: spec: names: kind: privileged targets: - target: admission.k8s.gatekeeper.sh rego: | package admission violation[{\"msg\": msg}] { # 如果violation为true(表达式通过)说明违反约束 containers = input.review.object.spec.template.spec.containers c_name := containers[0].name containers[0].securityContext.privileged # 如果返回true,说明违反约束 msg := sprintf(\"提示:'%v'容器禁止启用特权!\
约束:apiVersion: constraints.gatekeeper.sh/v1beta1kind: privilegedmetadata: name: privilegedspec: match: # 匹配的资源 kinds: - apiGroups: [\"apps\"] kinds: - \"Deployment\" - \"DaemonSet\" - \"StatefulSet“# 查看资源kubectl get constraints
禁止容器启用特权
模板:apiVersion: templates.gatekeeper.sh/v1beta1kind: ConstraintTemplatemetadata: name: image-checkspec: crd: spec: names: kind: image-check validation: openAPIV3Schema: properties: # 需要满足条件的参数 prefix: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package image violation[{\"msg\
约束:apiVersion: constraints.gatekeeper.sh/v1beta1kind: image-checkmetadata:name: image-checkspec:match:kinds:- apiGroups: [\"apps\"] kinds:- \"Deployment\"- \"DaemonSet\"- \"StatefulSet\"parameters: # 传递给opa的参数prefix: \"lizhenliang/
只允许使用特定的镜像仓库
apiVersion: templates.gatekeeper.sh/v1kind: ConstraintTemplatemetadata: name: k8srequiredlabelsspec: crd: spec: names: kind: K8sRequiredLabels validation: # Schema for the `parameters` field openAPIV3Schema: type: object properties: labels: type: array items: type: string targets: - target: admission.k8s.gatekeeper.sh rego: | package k8srequiredlabels violation[{\"msg\
命名空间必须要有gatekeeper标签apiVersion: constraints.gatekeeper.sh/v1beta1kind: K8sRequiredLabelsmetadata: name: ns-must-have-gkspec: match: kinds: - apiGroups: [\"\"] kinds: [\"Namespace\"] parameters: labels: [\"gatekeeper\"]
测试:# kubectl create ns test2Error from server (Forbidden): admission webhook \"validation.gatekeeper.sh\" denied the request: [ns-must-have-gk] you must provide labels: {\"gatekeeper\"}加上gk标签:apiVersion: v1kind: Namespacemetadata: labels: gatekeeper: test name: test2
namespace必须有gatekeeper标签
OPA Gatekeeper
Secret是一个用于存储敏感数据的资源,所有的数据要经过base64编码,数据实际会存储在K8s中Etcd,然后通过创建Pod时引用该数据。
• 变量注入• 数据卷挂载
Pod使用secret数据有两种方式:
• docker-registry:存储镜像仓库认证信息• generic:从文件、目录或者字符串创建,例如存储用户名密码• tls:存储证书,例如HTTPS证书
kubectl create secret 支持三种数据类型:
[root@master ~]# echo -n 123 |base64MTIz
apiVersion: v1kind: Secretmetadata: name: mysqltype: Opaquedata: mysql-root-password: \"MTIz\"---apiVersion: apps/v1kind: Deploymentmetadata: name: mysqlspec: selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: db image: mysql:5.7.30 env: - name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql key: mysql-root-password
将Mysql用户密码保存到Secret中存储
Secret存储敏感数据
容器的应用程序可以直接访问Linux内核的系统调用,容器在安全隔离上还是比较弱,虽然内核在不断地增强自身的安全特性,但由于内核自身代码极端复杂,CVE 漏洞层出不穷。所以要想减少这方面安全风险,就是做好安全隔离,阻断容器内程序对物理机内核的依赖。Google开源的一种gVisor容器沙箱技术就是采用这种思路,gVisor隔离容器内应用和内核之间访问,提供了大部分Linux内核的系统调用,巧妙的将容器内进程的系统调用转化为对gVisor的访问。gVisor兼容OCI,与Docker和K8s无缝集成,很方面使用。项目地址:https://github.com/google/gvisor
gVisor 拦截来自容器的系统调用,并通过用户空间内核运行它们, 用户空间内核采用 Go 编写,对底层主机的访问是受限的
基于硬件虚拟化隔离
基于规则的安全隔离,seccomp、AppArmor 和 SELinux 等
gVisor的隔离机制
不同类型的内核隔离
gVisor 由 3 个组件构成: • Runsc 是一种 Runtime 引擎,负责容器的创建与销毁。 • Sentry 负责容器内程序的系统调用处理。• Gofer 负责文件系统的操作代理,IO 请求都会由它转接到 Host 上。
gVisor架构
gVisor内核要求:Linux 3.17+CentOS7内核升级步骤:rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.orgrpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpmyum --enablerepo=elrepo-kernel install kernel-ml-devel kernel-ml –ygrub2-set-default 0rebootuname -r1、准备gVisor二进制文件sha512sum -c runsc.sha512rm -f *.sha512chmod a+x runscmv runsc /usr/local/bin2、Docker配置使用gVisorrunsc install # 查看加的配置/etc/docker/daemon.jsonsystemctl restart docker使用runsc运行容器:docker run -d --runtime=runsc nginx使用dmesg验证:docker run --runtime=runsc -it nginx dmesg
gVisor与Docker集成
切换Containerd容器引擎1、准备配置cat > /etc/sysctl.d/99-kubernetes-cri.conf << EOFnet.bridge.bridge-nf-call-iptables = 1net.ipv4.ip_forward = 1net.bridge.bridge-nf-call-ip6tables = 1EOFsysctl -system2、安装cd /etc/yum.repos.dwget http://mirrors.aliyun.com/docker\u0002ce/linux/centos/docker-ce.repoyum install -y containerd.io3、修改配置文件• pause镜像地址• Cgroup驱动改为systemd• 增加runsc容器运行时• 配置docker镜像加速器mkdir -p /etc/containerdcontainerd config default > /etc/containerd/config.tomlvi /etc/containerd/config.toml...[plugins.\"io.containerd.grpc.v1.cri\"]sandbox_image = \"registry.aliyuncs.com/google_containers/pause:3.2\" ...[plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc.options]SystemdCgroup = true...[plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runsc]runtime_type = \"io.containerd.runsc.v1\"[plugins.\"io.containerd.grpc.v1.cri\".registry.mirrors.\"docker.io\"]endpoint = [\"https://b9pmyelo.mirror.aliyuncs.com\"]...systemctl restart containerd4、配置kubelet使用containeredvi /etc/sysconfig/kubelet KUBELET_EXTRA_ARGS=--container-runtime=remote --container-runtime\u0002endpoint=unix:///run/containerd/containerd.sock --cgroup-driver=systemdsystemctl restart kubelet5、验证kubectl get node -o wide
gVisor与Containerd集成
准备crictl连接containerd配置文件:cat > /etc/crictl.yaml << EOFruntime-endpoint: unix:///run/containerd/containerd.sockEOF
gVisor
RuntimeClass 是一个用于选择容器运行时配置的特性,容器运行时配置用于运行 Pod 中的容器。
创建RuntimeClass:apiVersion: node.k8s.io/v1 # RuntimeClass 定义于 node.k8s.io API 组kind: RuntimeClassmetadata: name: gvisor # 用来引用 RuntimeClass 的名字handler: runsc # 对应的 CRI 配置的名称
创建Pod测试gVisor:apiVersion: v1kind: Podmetadata: name: nginx-gvisorspec: runtimeClassName: gvisor containers: - name: nginx image: nginxkubectl get pod nginx-gvisor -o widekubectl exec nginx-gvisor -- dmesg
RuntimeClass
安全沙箱运行容器
4、最小化微服务漏洞
主要功能从内核运行时采集Linux系统调用。提供了一套强大的规则引擎,用于对Linux系统调用行为进行监控。当系统调用违反规则时,会触发相应的告警。
Falco可以对Linux系统调用行为进行监控。
Falco架构
架构:Falco内核模块持续采集Linxu内核态系统调用,并将采集到的系统调用事件通过ring buffer传递到用户态。Falco用户态模块解析系统调用事件,并经过配置的Falco规则处理识别出异常事件。异常事件通过告警发送到标准输出、gRPC调用等。Falco的组成:用户态进程Userspace program:解析从driver接收到的时间,并发送告警。配置信息:定义了Falco的运行配置,规则定义,告警配置等。Driver:默认内核模块,基于libscap、libsinsp构建。BPF探针Userspace instrumentation
rpm --import https://falco.org/repo/falcosecurity-3672BA8F.asccurl -s -o /etc/yum.repos.d/falcosecurity.repo https://falco.org/repo/falcosecurity-rpm.repoyum install epel-release -yyum updateyum install falco -ysystemctl start falcosystemctl enable falco
安装falco
falco配置文件目录:/etc/falco• falco.yaml falco配置与输出告警通知方式• falco_rules.yaml 规则文件,默认已经定义很多威胁场景• falco_rules.local.yaml 自定义扩展规则文件• k8s_audit_rules.yaml K8s审计日志规则
配置文件
告警规则示例(falco_rules.local.yaml):- rule: The program \"sudo\" is run in a container desc: An event will trigger every time you run sudo in a container condition: evt.type = execve and evt.dir=< and container.id != host and proc.name = sudo output: \"Sudo run in container (user=%user.name %container.info parent=%proc.pname cmdline=%proc.cmdline)\
1、监控系统二进制文件目录读写(默认规则)2、监控根目录或者/root目录写入文件(默认规则)3、监控运行交互式Shell的容器(默认规则)4、监控容器创建的不可信任进程(自定义规则)验证:tail -f /var/log/messages(告警通知默认输出到标准输出和系统日志)
威胁场景测试
监控容器创建的不可信任进程规则,在falco_rules.local.yaml文件添加:- rule: Unauthorized process on nginx containers condition: spawned_process and container and container.image startswith nginx and not proc.name in (nginx) desc: test output: \"Unauthorized process on nginx containers (user=%user.name container_name=%container.name container_id=%container.id image=%container.image.repository shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline terminal=%proc.tty)\" priority: WARNINGcondition表达式解读:• spawned_process 运行新进程• container 容器• container.image startswith nginx 以nginx开头的容器镜像• not proc.name in (nginx) 不属于nginx的进程名称(允许进程名称列表)重启falco应用新配置文件:systemctl restart falco
创建规则
• 输出到标准输出(默认启用)• 输出到文件• 输出到Syslog(默认启用)• 输出到HTTP服务• 输出到其他程序(命令行管道方式)告警配置文件:/etc/falco/falco.yaml例如输出到指定文件:file_output: enabled: true keep_alive: false filename: /var/log/falco_events.log
Falco支持五种输出告警通知的方式
• FalcoSideKick:一个集中收集并指定输出,支持大量方式输出,例如Influxdb、Elasticsearch等项目地址 https://github.com/falcosecurity/falcosidekick• FalcoSideKick-UI:告警通知集中图形展示系统项目地址 https://github.com/falcosecurity/falcosidekick-ui
部署Falco UI:docker run -d \\ -p 2801:2801 \\--name falcosidekick \\ -e WEBUI_URL=http://192.168.31.71:2802 \\falcosecurity/falcosidekickdocker run -d \\ -p 2802:2802 \\--name falcosidekick-ui \\falcosecurity/falcosidekick-uiUI访问地址:http://192.168.31.71:2802/ui/修改falco配置文件指定http方式输出:json_output: truejson_include_output_property: truehttp_output: enabled: true url: \"http://192.168.31.71:2801/\"
Falco告警集中化展示
监控容器运行时:Falco
在Kubernetes集群中,API Server的审计日志记录了哪些用户、哪些服务请求操作集群资源,并且可以编写不同规则,控制忽略、存储的操作日志。审计日志采用JSON格式输出,每条日志都包含丰富的元数据,例如请求的URL、HTTP方法、客户端来源等,你可以使用监控服务来分析API流量,以检测趋势或可能存在的安全隐患。这些可能服务会访问API Server: • 管理节点(controller-manager、scheduler) • 工作节点(kubelet、kube-proxy) • 集群服务(CoreDNS、Calico、HPA等) • kubectl、API、Dashboard
当客户端向 API Server发出请求时,该请求将经历一个或多个阶段:阶段 说明RequestReceived 审核处理程序已收到请求ResponseStarted 已发送响应标头,但尚未发送响应正文ResponseComplete 响应正文已完成,不再发送任何字节Panic 内部服务器出错,请求未完成
事件和阶段
Kubernetes审核策略文件包含一系列规则,描述了记录日志的级别,采集哪些日志,不采集哪些日志。规则级别如下表所示:级别 说明None 不为事件创建日志条目Metadata 创建日志条目。包括元数据,但不包括请求正文或响应正文Request 创建日志条目。包括元数据和请求正文,但不包括响应正文RequestResponse 创建日志条目。包括元数据、请求正文和响应正文
审计日志格式
参数说明audit-policy-file 审计日志策略文件audit-log-path 审计日志输出文件audit-log-maxage 审计日志保留的最大天数audit-log-maxbackup 审计日志最大分片存储多少个日志文件audit-log-maxsize 单个审计日志最大大小,单位MB
审计日志支持写入本地文件和Webhook(发送到外部HTTP API)两种方式。启用审计日志功能:vi /etc/kubernetes/manifests/kube-apiserver.yaml… - --audit-policy-file=/etc/kubernetes/audit/audit-policy.yaml - --audit-log-path=/var/log/k8s_audit.log - --audit-log-maxage=30 - --audit-log-maxbackup=10 - --audit-log-maxsize=100...volumeMounts:...- mountPath: /etc/kubernetes/audit/audit-policy.yaml name: audit- mountPath: /var/log/k8s_audit.log name: audit-log volumes: - name: audit hostPath: path: /etc/kubernetes/audit/audit-policy.yaml type: File - name: audit-log hostPath: path: /var/log/k8s_audit.log type: FileOrCreate注:需要使用hostpath数据卷将宿主机策略文件和日志文件挂载到容器中
只记录指定资源操作日志apiVersion: audit.k8s.io/v1kind: Policy# 忽略步骤,不为RequestReceived阶段生成审计日志omitStages: - \"RequestReceived\"rules: # 不记录日志 - level: None users: - system:apiserver - system:kube-controller-manager - system:kube-scheduler - system:kube-proxy - kubelet # 针对资源记录日志 - level: Metadata resources: - group: \"\" resources: [\"pods\"]# - group: \"apps\"# resources: [\"deployments\"]# 其他资源不记录日志 - level: None
• 审计日志文件+filebeat• 审计webhook+logstash• 审计webhook+falco
收集审计日志方案
Kubernetes 审计日志
6、监控、审计和运行时安全
集群安全:TLS证书认证、RBAC
Security Context:限制容器的行为
Pod Security Policy:集群级的Pod安全策略,自动为集群内的 Pod 配置安全策略
Sysctls:允许容器设置内核参数
AppArmor:限制容器中应用对资源的访问权限
Network Policies:控制集群中网络通信
Seccomp:限制容器内进程的系统调用
安全机制
互联网安全中心(CIS,Center for Internet Security),是一个非盈利组织,致力为互联网提供免费的安全防御解决方案。
Kube-bench是容器安全厂商Aquq推出的工具,以CIS K8s基准作为基础,来检查K8s是否安全部署。主要查找不安全的配置参数、敏感的文件权限、不安全的帐户或公开端口等等。
介绍
1、下载二进制包https://github.com/aquasecurity/kube-bench/releases
2、解压使用tar zxvf kube-bench_0.6.3_linux_amd64.tar.gz mkdir /etc/kube-bench # 创建默认配置文件路径mv cfg /etc/kube-bench/cfg
部署
示例:检查master组件安全配置kube-bench run --targets=master
测试项目配置文件:/etc/kube-bench/cfg/cis-1.6/• id:编号• text:提示的文本• audit: • tests:测试项目• remediation:修复方案• scored:如果为true,kube-bench无法正常测试,则会生成FAIL,如果为false,无法正常测试,则会生成WARN。 • type:如果为manual则会生成WARN,如果为skip,则会生成INFO
使用
CIS基准测试工具:kube-beach
CIS安全基准
K8s中的一个抽象资源,给管理员提供一个暴露应用的入口定义方法
Ingress
根据Ingress生成具体的路由规则,并对Pod负载均衡器
Ingress Controller
HTTPS是安全的HTTP,HTTP 协议中的内容都是明文传输,HTTPS 的目的是将这些内容加密,确保信息传输安全。最后一个字母 S 指的是 SSL/TLS 协议,它位于HTTP 协议与 TCP/IP 协议中间。
HTTPS优势:1、加密隐私数据:防止您访客的隐私信息(账号、地址、手机号等)被劫持或窃取。 2、安全身份认证:验证网站的真实性,防止钓鱼网站。 3、防止网页篡改:防止数据在传输过程中被篡改,保护用户体验。 4、地址栏安全锁:地址栏头部的“锁”型图标,提高用户信任度。 5、提高SEO排名:提高搜索排名顺序,为企业带来更多访问量。
配置HTTPS步骤:1、准备域名证书文件(来自:openssl/cfssl工具自签或者权威机构颁发) 2、将证书文件保存到Secretkubectl create secret tls web-aliangedu-cn --cert=web.aliangedu.cn.pem --key=web.aliangedu.cn-key.pem3、Ingress规则配置tls4、kubectl get ingress5、测试,本地电脑绑定hosts记录对应ingress里面配置的域名,IP是Ingress Concontroller Pod节点IP
https
Ingress配置证书
Kubernetes 集群网络没任何网络限制,Pod 可以与任何其他 Pod 通信,在某些场景下就需要进行网络控制,减少网络攻击面,提高安全性,这就会用到网络策略。
默认情况下
是一个K8s资源,用于限制Pod出入流量,提供Pod级别和Namespace级别网络访问控制。
采用的是白名单模式,符合规则的通过,不符合规则的拒绝。
网络策略(Network Policy)
• 应用程序间的访问控制,例如项目A不能访问项目B的Pod• 开发环境命名空间不能访问测试环境命名空间Pod• 当Pod暴露到外部时,需要做Pod白名单• 多租户网络环境隔离
网络策略的应用场景
podSelector:目标Pod,根据标签选择。policyTypes:策略类型,指定策略用于入站、出站流量。Ingress:from是可以访问的白名单,可以来自于IP段、命名空间、Pod标签等,ports是可以访问的端口。Egress:这个Pod组可以访问外部的IP段和端口。
网络策略
ipBlock:匹配到的IP地址可以访问,except匹配到的无法访问 ;注意, 这些应该是集群外部 IP,因为 Pod IP存在时间短暂的且随机产生。例如,所作用的源IP则可能是LoadBalancer或Pod的node等。podSelector:指定匹配到label的pod能够访问被保护的pod;namespaceSelector:指定具体命名空间内的pod能够访问被保护的pod。
三种设置策略的方式
1、创建Network Policy资源2、Policy Controller监控网络策略,同步并通知节点上程序3、节点上DaemonSet运行的程序从etcd中获取Policy,调用本地Iptables创建防火墙规则
网络策略工作流程:
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-all namespace: testspec: podSelector: {} # 匹配本命名空间所有pod policyTypes: - Ingress - Egress # ingress和egress没有指定规则,则不允许任何流量进出pod
拒绝命名空间下所有Pod入、出站流量
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: deny-all-namespaces namespace: testspec: podSelector: {} policyTypes: - Ingress ingress: - from: - podSelector: {} # 匹配本命名空间所有pod
拒绝其他命名空间Pod访问
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: allow-all-namespaces namespace: testspec: podSelector: matchLabels: app: web policyTypes: - Ingress ingress: - from: - namespaceSelector: {} # 匹配所有命名空间的pod
允许其他命名空间Pod访问指定应用
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: app-to-app namespace: testspec: podSelector: matchLabels: run: web policyTypes: - Ingress ingress: - from: - podSelector: matchLabels: run: client1 ports: - protocol: TCP port: 80
同一个命名空间下应用之间限制访问
apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata: name: dev-web namespace: devspec: podSelector: matchLabels: env: dev policyTypes: - Ingress ingress: # 满足允许prod命名空间中的pod访问 - from: - namespaceSelector: matchLabels: env: prod # 允许pod标签为app=client1的pod访问,所有命名空间 - from: - namespaceSelector: {} podSelector: matchLabels: app: client1
只允许指定命名空间中的应用访问
案例
网络访问控制
1、集群部署与安全配置
K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件。1. Authentication(鉴权)2. Authorization(授权)3. Admission Control(准入控制)
K8s Apiserver提供三种客户端身份认证: • HTTPS 证书认证:基于CA证书签名的数字证书认证(kubeconfig)• HTTP Token认证:通过一个Token来识别用户(serviceaccount) • HTTP Base认证:用户名+密码的方式认证(1.19版本弃用)
认证(Authentication)
RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。RBAC根据API请求属性,决定允许还是拒绝。比较常见的授权维度:• user:用户名• group:用户分组• 资源,例如pod、deployment• 资源操作方法:get,list,create,update,patch,watch,delete• 命名空间• API组
授权(Authorization)
准入控制(Admission Control)
kubernetes安全框架
RBAC(Role-Based Access Control,基于角色的访问控制),是K8s默认授权策略,并且是动态配置策略(修改即时生效)。
主体(subject) • User:用户• Group:用户组• ServiceAccount:服务账号角色• Role:授权特定命名空间的访问权限• ClusterRole:授权所有命名空间的访问权限角色绑定• RoleBinding:将角色绑定到主体(即subject) • ClusterRoleBinding:将集群角色绑定到主体注:RoleBinding在指定命名空间中执行授权,ClusterRoleBinding在集群范围执行授权。
内置集群角色 描述cluster-admin 超级管理员,对集群所有权限admin 主要用于授权命名空间所有读写权限edit 允许对命名空间大多数对象读写操作,不允许查看或者修改角色、角色绑定。view 允许对命名空间大多数对象只读权限,不允许查看角色、角色绑定和Secret
k8s预定好了四个集群角色供用户使用,使用kubectl get clusterrole查看,其中systemd:开头的为系统内部使用。
1、为用户生成私钥,权限应为600$ (umask 077; openssl genrsa -out $HOME/.certs/vagrant.key 2048)2、创建证书签署请求,-subj参数的CN值为用户名,O的值为用户组openssl req -new -key $HOME/.certs/vagrant.key -out $HOME/.certs/vagrant.csr -subj \"/CN=vagrant/O=test\"3、用CA签署证书,设置时长sudo openssl x509 -req -days 365 -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -in $HOME/.certs/vagrant.csr -out $HOME/.certs/vagrant.crt4、验证生成的数字证书信息(可选)$ openssl x509 -in $HOME/.certs/vagrant.crt -text -noout
创建用户
设置身份凭据,自动在vagrant家目录下生成.kube/config文件$ kubectl config set-credentials vagrant --embed-certs=true --client-certificate=$HOME/.certs/vagrant.crt --client-key=$HOME/.certs/vagrant.key设置上下文$ kubectl config set-context vagrant@kubernetes --cluster=kubernetes --user=vagrant设置集群信息$ kubectl config set-cluster kubernetes --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server=\"https://10.0.0.10:6443\" --kubeconfig=$HOME/.kube/config
为用户生成kubeconfig配置文件
角色权限分配
给vagrant用户绑定read-pods角色# kubectl create rolebinding read-pods -n default --role=read-pods --user=vagrant --dry-run=client -oyamlapiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: read-pods namespace: defaultsubjects:- kind: User # 主体 name: vagrant # 主体名称 apiGroup: rbac.authorization.k8s.ioroleRef: # 绑定的角色 kind: Role name: pod-reader # 角色名称 apiGroup: rbac.authorization.k8s.io
将主体与角色绑定
为test用户组统一授权:# kubectl create rolebinding read-pods -n default --role=read-pods --group=test --dry-run=client -oyamlapiVersion: rbac.authorization.k8s.io/v1kind: RoleBindingmetadata: name: read-pods namespace: defaultsubjects:- kind: Group name: dev apiGroup: rbac.authorization.k8s.ioroleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
用户组:用户组的好处是无需单独为某个用户创建权限,统一为这个组名进行授权,所有的用户都以组的身份访问资源。
为指定用户授权访问default命名空间Pod读取权限大致步骤:1. 用K8S CA签发客户端证书2. 生成kubeconfig授权文件3. 创建RBAC权限策略4. 指定kubeconfig文件测试权限:kubectl get pods --kubeconfig=./aliang.kubeconfig
对用户授权访问K8s(TLS证书)
先了解下ServiceAccount,简称SA,是一种用于让程序访问K8s API的服务账号。• 当创建namespace时,会自动创建一个名为default的SA,这个SA没有绑定任何权限• 当default SA创建时,会自动创建一个default-token-xxx的secret,并自动关联到SA• 当创建Pod时,如果没有指定SA,会自动为pod以volume方式挂载这个default SA,在容器目录:/var/run/secrets/kubernetes.io/serviceaccount验证默认SA权限:kubectl --as=system:serviceaccount:default:default get pods
yaml文件apiVersion: v1kind: ServiceAccountmetadata: name: app-demo namespace: test---apiVersion: rbac.authorization.k8s.io/v1kind: Rolemetadata: name: role-test namespace: testrules:- apiGroups: [\"apps\"] resources: [\"deployments\
需求:授权容器中Python程序对K8s API访问权限实施大致步骤:1. 创建Role2. 创建ServiceAccount3. 将ServiceAccount与Role绑定4. 为Pod指定自定义的SA5. 进入容器里执行Python程序测试操作K8s API权限
对应用程序授权访问K8s(ServiceAccount)
基于角色的权限访问控制:RBAC
当多个团队、多个用户共享使用K8s集群时,会出现不均匀资源使用,默认情况下先到先得,这时可以通过ResourceQuota来对命名空间资源使用总量做限制,从而解决这个问题。使用流程:k8s管理员为每个命名空间创建一个或多个ResourceQuota对象,定义资源使用总量,K8s会跟踪命名空间资源使用情况,当超过定义的资源配额会返回拒绝。
ResourceQuota功能是一个准入控制插件,默认已经启用。
支持的资源 描述limits.cpu/memory 所有Pod上限资源配置总量不超过该值(所有非终止状态的Pod)requests.cpu/memory 所有Pod请求资源配置总量不超过该值(所有非终止状态的Pod)cpu/memory 等同于requests.cpu/requests.memoryrequests.storage 所有PVC请求容量总和不超过该值persistentvolumeclaims 所有PVC数量总和不超过该值<storage-class-name>.storageclass.storage.k8s.io/requests.storage 所有与<storage-class-name>相关的PVC请求容量总和不超过该值<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims 所有与<storage-class-name>相关的PVC数量总和不超过该值pods、count/deployments.apps、count/statfulsets.apps、count/services(services.loadbalancers、services.nodeports)、count/secrts、count/configmaps、count/job.batch、count/cronjobs.batch 创建资源数量不超过该值
apiVersion: v1kind: ResourceQuotametadata: name: object-counts namespace: testspec: hard: pods: \"10\" count/deployments.apps: \"3\" count/services: \"3\"
对象数量配额
apiVersion: v1kind: ResourceQuotametadata: name: compute-resources namespace: testspec: hard: requests.cpu: \"4\" requests.memory: 10Gi limits.cpu: \"6\" limits.memory: 12Gi
计算资源配额
apiVersion: v1kind: ResourceQuotametadata: name: storage-resources namespace: testspec: hard: requests.storage: \"10G\" managed-nfs\u0002storage.storageclass.storage.k8s.io/requests.storage: \"5G\"
存储资源配额
kubectl get quota -n test
查看配额
资源配额 ResourceQuota
默认情况下,K8s集群上的容器对计算资源没有任何限制,可能会导致个别容器资源过大导致影响其他容器正常工作,这时可以使用LimitRange定义Pod和容器默认CPU和内存请求值或者最大上限。LimitRange限制维度:• 限制容器配置requests.cpu/memory,limits.cpu/memory的最小、最大值• 限制容器配置requests.cpu/memory,limits.cpu/memory的默认值 • 限制PVC配置requests.storage的最小、最大值
apiVersion: v1kind: LimitRangemetadata: name: cpu-memory-min-max namespace: testspec: limits: - max: # 容器能设置limit的最大值 cpu: 1 memory: 1Gi min: # 容器能设置request的最小值 cpu: 200m memory: 200Mi type: Container
计算资源最大、最小限制
apiVersion: v1kind: LimitRangemetadata: name: cpu-memory-min-max namespace: testspec: limits: - default: cpu: 500m memory: 500Mi defaultRequest: cpu: 300m memory: 300Mi type: Container
计算资源默认值限制
apiVersion: v1kind: LimitRangemetadata: name: storage-min-max namespace: testspec: limits: - type: PersistentVolumeClaim max: storage: 10Gi min: storage: 1Gi
存储资源最大、最小限制
kubectl get limits -n testkubectl describe limits -n test
查看限制
资源限制 LimitRange
2、集群强化
可信任软件供应链:指在建设基础架构过程中,涉及的软件都是可信任的。
在K8s领域可信软件供应链主要是指镜像,因为一些软件交付物都是镜像,部署的最小载体。
可信任软件供应链
• 减少镜像层:一次RUN指令形成新的一层,尽量Shell命令都写在一行,减少镜像层。 • 清理无用文件:清理对应的残留数据,例如yum缓存。• 清理无用的软件包:基础镜像默认会带一些debug工具,可以删除掉,仅保留应用程序所需软件,防止黑客利用。 • 选择最小的基础镜像:例如alpine• 使用非root用户运行:USER指令指定普通用户
构建python web镜像FROM pythonRUN useradd pythonRUN mkdir /data/www -pCOPY . /data/wwwRUN chown -R python /dataRUN pip install flask -i https://mirrors.aliyun.com/pypi/simple/WORKDIR /data/wwwUSER pythonCMD python main.py
构建镜像Dockerfile文件优化
Trivy:是一种用于容器镜像、文件系统、Git仓库的漏洞扫描工具。发现目标软件存在的漏洞。Trivy易于使用,只需安装二进制文件即可进行扫描,方便集成CI系统。
镜像漏洞扫描工具:Trivy
kubesec:是一个针对K8s资源清单文件进行安全配置评估的工具,根据安全配置最佳实践来验证并给出建议。
示例:kubesec scan deployment.yaml或者使用容器环境执行检查docker run -i kubesec/kubesec scan /dev/stdin < deployment.yamlkubesec内置一个HTTP服务器,可以直接启用,远程调用。• 二进制kubesec http 8080 &• Docker容器docker run -d -p 8080:8080 kubesec/kubesec http 8080示例:curl -sSX POST --data-binary @deployment.yaml http://192.168.31.71:8080/scan
检查YAML文件安全配置:kubesec
Admission Webhook:准入控制器Webhook是准入控制插件的一种,用于拦截所有向APISERVER发送的请求,并且可以修改请求或拒绝请求。Admission webhook为开发者提供了非常灵活的插件模式,在kubernetes资源持久化之前,管理员通过程序可以对指定资源做校验、修改等操作。例如为资源自动打标签、pod设置默认SA,自动注入sidecar容器等。
相关Webhook准入控制器:• MutatingAdmissionWebhook:修改资源,理论上可以监听并修改任何经过ApiServer处理的请求• ValidatingAdmissionWebhook:验证资源• ImagePolicyWebhook:镜像策略,主要验证镜像字段是否满足条件
准入控制器Admission Webhook
2、准备配置文件# /etc/kubernetes/image-policy/admission_configuration.yamlapiVersion: apiserver.config.k8s.io/v1kind: AdmissionConfigurationplugins:- name: ImagePolicyWebhook configuration: imagePolicy: kubeConfigFile: /etc/kubernetes/image-policy/connect_webhook.yaml # 连接镜像策略服务器配置文件 allowTTL: 50 # 控制批准请求的缓存时间,单位秒 denyTTL: 50 # 控制批准请求的缓存时间,单位秒 retryBackoff: 500 # 控制重试间隔,单位毫秒 defaultAllow: true # 确定webhook后端失效时的行为
2、准备配置文件# /etc/kubernetes/image-policy/kubeconfig.yamlapiVersion: v1kind: Configclusters:- cluster: certificate-authority: /etc/kubernetes/image-policy/webhook.pem # 数字证书,用于验证远程服务 server: https://192.168.31.73:8080/image_policy # 镜像策略服务器地址,必须是https name: webhookcontexts:- context: cluster: webhook user: apiserver name: webhookcurrent-context: webhook preferences: {}users:- name: apiserver user: client-certificate: /etc/kubernetes/image-policy/apiserver-client.pem # webhook准入控制器使用的证书client-key: /etc/kubernetes/image-policy/apiserver-client-key.pem # 对应私钥证书
3、部署镜像服务器自己用python开发一个简单的webhook端点服务器,作用是拒绝部署的镜像乜有指定标签(即latest)。3.1 自签HTTPS证书3.2 Docker容器启动镜像策略服务docker run -d -u root --name=image-policy-webhook \\ -v $PWD/webhook.pem:/data/www/webhook.pem \\ -v $PWD/webhook-key.pem:/data/www/webhook-key.pem \\ -e PYTHONUNBUFFERED=1 -p 8080:8080 \\lizhenliang/image-policy-webhook
4、测试kubectl create deployment web1 --image=nginx:1.16kubectl create deployment web2 --image=nginx
准入控制器: ImagePolicyWebhook
5、供应链安全
cks
0 条评论
回复 删除
下一页