背景
应用上云后我的应用安全该如何保证,云原生语义下软件的生命周期:开发->分发->部署->运行,这一系列过程中,安全贯穿始终。下面将介绍一下各个流程中的安全保证。
1.应用开发
开发过程中有安全需求,代码也有安全扫描SCM,比如最近的log4j2漏洞。
2.应用分发
代码安全扫描通过后,经过流水线CI/CD构建成容器镜像,分发的环节就是确保镜像没有安全漏洞。
- 镜像推送到镜像中心的不同仓库。
- 镜像进行单元测试,集成测试,系统测试。
- 通过Clair或者anchor进行镜像扫描,可以通过imagePullPolicy定义webhook,没有通过镜像扫描的镜像就不能部署。
- 防止镜像被篡改,需要对镜像进行签名,保证镜像的完整性。镜像的digest就是签名的哈希值。
- 拉取镜像运行时会进行签名校验。
3.应用部署
需要做以下运行前的检查:
- 镜像签名及完整性
- 镜像运行策略(如没有恶意软件或严重的漏洞)
- 容器运行策略(如无过度权限)
- 主机安全漏洞和合规性控制
- 工作负载、应用程序和网络安全策略
4.应用运行
- 只有经过批准的进程能在容器命名空间内运行;即容器是否要以root用户来运行,让容器以非root用户运行,只对某些进程有操作权限,保证容器安全。
- 禁止并报告未经授权的资源访问;
- 监控网络流量以检测恶意的活动;
- 服务网格是另一种常见的服务层抽象,它为已经编排的服务提供了整合和补充功能,而不会改变工作负载软件本身(例如,API 流量的日志记录、传输加密、可观察性标记、认证和授权)。
运行环境
从下到上:
- 云的访问日志。
2.RAM用户;安全组;操作系统只有部分目录可以操作,其他不可操作即Immutable os;存储加密。
3.通过VPC等进行访问控制。
4.k8s提供了很多安全保证,开启审计日志后,集群中任何应用等变更都会记录是谁哪个ip来操作的。
5.RBAC,admission controll(防止恶意镜像)。
6.network policy控制应用的连通性。
7.pod/container security定义pod和容器的安全上下文。
8.最上层就是service mesh
容器运行时安全保证
重点是控制只有经过授权的应用才可以被执行。
以 Non-root 身份运行容器
默认情况下,编写dockerfile中用户都是root用户,所以需要切换用户为非root用户。防止某些坏的镜像窃取主机的 root 权限并造成危害。
- 有些运行时容器内部的 root 用户与主机的 root 用户是同一个用户,如不进行用户切换很可能因为权限过大引发严重的问题,比如一个最简单的 case,主机上的重要文件夹被 mount 到容器内部,并被容器修改配置。
- 即使在容器内部也应该进行权限隔离,比如当我们希望构建不可变配置的容器镜像时,应该将运行容器的用户切换为非 root 用户,并且限制其读写权限和读写目录。
可以通过user命令来切换。
FROM centos
RUN user add wgh
USER wgh
User Namespace
- 依赖于 User namespace,任何容器内部的用户都会映射成主机的非 root 用户。
- 但该功能未被默认 enable,因其引入配置复杂性,比如系统不知道主机用户和容器用户的映射关系,在 mount 文件的时候无法设置适当的权限。
Rootless container
- rootless container 是指容器运行时以非 root 身份启动。
- 在该配置下,即使容器被突破,在主机层面获得的用户权限也是非 root 身份的用户,这确保了安全。
- Docker 和其他运行时本身的后台 Daemon(如 Docker Daemon) 需要 root 身份运行,然后其他用户的容器才能以 rootless 身份运行。
- 一些运行时,比如 Podman,无需 Daemon 进程,因为可以完全不需要 root 身份。
集群安全保证
- 保证容器与容器之间、容器与主机之间隔离,限制容器对其他容器和主机的消极影响。
- 保证组件、用户及容器应用程序都是最小权限,限制它们的权限范围。
- 保证集群的敏感数据的传输和存储安全。
集群的安全通信
- etcd之间要进行通信,通过双向的grpc进行连接,可以配置TLS证书,即通信是加密的。
2.etcd也要和APIserver进行通信,也可以配置TLS证书加密。
3.APIserver本身是开启了https。
4.kubelet连接APIserver也是通过TLS证书加密。
控制面安全保证
认证,授权,审计,准入(配额管理)
参考文章:https://wghdr.top/archives/335
NodeRestriction
- 准入控制器限制了 kubelet 可以修改的 Node 和 Pod 对象,kubelet 只可修改自己的Node API 对象,只能修改绑定到节点本身的 Pod 对象。
- NodeRestriction 准入插件可防止 kubelet 删除 Node APl 对象。
- 防止 kubelet 添加/删除/更新带有 node-restriction.kubernetes.io/ 前缀的标签。
- 将来的版本可能会增加其他限制,以确保 kubelet 具有正常运行所需的最小权限集。
为什么要加这个插件?
降低获得 kubelet kubeconfig 的人能做成的破坏。即只能删除一个node,不能破坏其他node。
存储加密
参考文档:https://kubernetes.io/zh/docs/tasks/administer-cluster/encrypt-data/
通过EncryptionConfiguration指定secret的加密密钥,或者通过外部的kms来管理secret。这样数据在落盘的时候,数据就是加密的。
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- identity: {}
- aesgcm:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- secretbox:
keys:
- name: key1
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
pod安全保证
pod层级主要通过SecurityContext和PodSecurityPolicy来保证安全。
参考文章:https://wghdr.top/archives/1159
Taint
可以以租户为粒度,为不同租户的节点增加 Taint,使得节点彼此隔离。
Taint 的作用是让租户独占节点,无对应 Toleration 的 Pod 无法被调度到 Taint 节点上,实现了应用部署的隔离。保证了部署过程中没有安全漏洞。
# 使用命令 kubectl taint 给节点增加一个 Taint:
kubectl taint nodes node1 key=value: NoSchedule
# 运行如下命令删除 Taint:
kubectl taint nodes node1 key: NoSchedule-
在podSpec中定义容忍tolerations:
tolerations:
key: "key"
operator: "Exists"
effect: "NoSchedule"
应用间的安全保证
应用部署到集群后,怎么控制应用间的访问,可以通过NetworkPolicy来保证应用安全。
参考文章:https://wghdr.top/archives/1194