LabHub
学习 学习路径 课程

CKS — Kubernetes 安全专家

没留下的日志,等于没发生过

在 LabHub 中继续学习

一句话总结

审计策略不是决定“记录什么”,而是决定“丢弃什么”的文档。规则会从上到下 依次求值,并且只应用第一个匹配项,因此顺序写错后,可能悄无声息地什么都没留下。

概念图: 一句话总结 · 为什么需要它 · 工作原理 · 现场会遇到的情况

为什么需要它

事件响应的第一个问题总是相同:何时、由谁、做了什么。在 Kubernetes 中,唯一能回答 这个问题的资料就是 API 服务器的审计日志。然而,全部记录会使存储成本激增, 随意记录又会在真正需要时一无所获。因此需要审计策略。

日志级别分为四档。

级别 记录范围
None 不记录
Metadata 只记录请求者、时间、动词、资源等元数据
Request 元数据 + 请求正文
RequestResponse 元数据 + 请求正文 + 响应正文

CKS 在这里会反复考查一个陷阱:如果对 Secret 设置 RequestResponse, Secret 的值会原样写进审计日志文件。审计日志通常会被收集到一个访问权限比应用更宽泛的 位置,因此原本为了保护 Secret 的措施,反而会造成 Secret 扩散。 所以,Secret 和 ConfigMap 通常最多只记录到 Metadata

工作原理

策略文件是 audit.k8s.io/v1Policy 资源,它从上到下检查 rules 数组, 并应用第一个匹配的规则。因此,顺序本身就有含义。例如,如果想排除 kube-system 中 对 Secret 的 get 请求,对应的 level: None 规则就必须放在 Secret 相关规则之前。 如果放在后面,请求会先匹配上方规则,排除操作完全不会生效。

还会配合使用 omitStages。一个请求可能在 RequestReceivedResponseStartedResponseCompletePanic 四个阶段生成事件,而 RequestReceived 几乎总是噪声。 把这个阶段写入顶层 omitStages,可以显著减少日志量。

创建策略文件后,还必须将其连接到 API 服务器。通过 --audit-policy-file 指定策略, 通过 --audit-log-path 指定输出位置,再用 --audit-log-maxage(保留天数)、 --audit-log-maxbackup(文件数量)、--audit-log-maxsize(MB)设定轮转策略。 缺少这三项会使磁盘逐渐写满,而磁盘写满后,API 服务器就会停止工作。

RBAC 中的高风险动词需要特殊处理。escalatebindimpersonate 本身就是权限提升尝试, 因此应以 RequestResponse 记录,以便保留试图修改什么、如何修改的完整信息。 对于 Pod 变更,Request 是较好的平衡点。保留清单即可在入侵后重建曾部署过什么, 通常不需要连响应正文也记录下来。

现场会遇到的情况

有些领域无法通过审计日志回答,运行时检测会补上这一空缺。Falco 观察内核系统调用, 并对符合规则的行为发出告警。它最知名的内置规则之一,是捕获容器内启动 Shell 的瞬间; 其条件大致是在 evt.type=execve 的基础上,再叠加是否处于容器中,以及进程名称是否 位于 Shell 列表中。没有经过 API 的行为根本不会出现在审计日志里, 所以这两个层面并非替代关系,而是回答不同问题的工具。

可以用 crictl 检查节点上实际运行的内容,但必须守住边界。 crictl 会绕过 API 服务器,因此非常适合诊断,拿来改变状态却很危险。kubelet 会持续监控 自己创建的容器和沙箱;如果人工执行 crictl rm 删除它们,kubelet 的认知与实际状态就会 发生偏差,系统会停留在异常的中间状态。规则可以简单概括为:想知道 Kubernetes 试图做什么, 就使用 kubectl;想知道运行时实际上做了什么,就使用 crictl。两种视角发生偏差的位置, 正是问题所在。

还有一种情况会让整套诊断失去意义:如果 crictl 连接了错误的套接字,它会显示空列表, 从而让人得出“一个容器都没有”的错误结论。第一步应先运行 crictl info 确认当前连接目标, 再核对 /etc/crictl.yaml 中的 runtime-endpoint 是否与 kubelet 的 --container-runtime-endpoint 一致。如果没有明确指定端点,crictl 还会依次尝试已知的 套接字候选项,导致一条命令也可能耗时十几秒。

发现遭入侵的 Pod 后,处置顺序也有明确要求。第一步不是立刻删除,而是保全证据。 先收集日志和状态,再用 NetworkPolicy 切断该 Pod 的通信并实施隔离,确认入侵路径与范围后, 最后替换为已修复漏洞的新镜像。如果先删除,取证证据就会消失。

下一实验要做什么

你将逐条构建 audit.k8s.io/v1 策略文件。从最底部的兜底规则开始, 通过 omitStages 减少噪声;Secret 最多记录到 Metadata,kube-system 中的 Secret get 完全设为 None,RBAC 高风险动词设为 RequestResponse,Pod 变更设为 Request, 并亲自安排这些规则的顺序。最后,还要记录连接 API 服务器所需的审计日志后端标志。