EKS安全红线:如何审计并告警 kubectl exec 和 port-forward 等高危操作?

158 阅读6分钟

引言:当 kubectl 成为一把双刃剑

大家好,在Kubernetes的世界里,kubectl 是我们手中最强大的“瑞士军刀”。它让我们能够轻松地与集群交互,部署应用,排查故障。然而,这把“军刀”中最锋利的两刃——kubectl execkubectl port-forward,也可能成为最危险的安全后门。

  • kubectl exec:允许用户在Pod内容器中执行任意命令,相当于一个直通容器内部的Shell。如果被滥用,攻击者可以窃取敏感信息、横向移动或植入恶意软件。
  • kubectl port-forward:能够将本地端口流量转发到Pod的端口,直接暴露了集群内部的网络服务,绕过了Ingress、Service等所有网络策略和安全控制。

对于任何一个生产环境的EKS集群,放任这些操作而不进行监控,无异于“夜不闭户”。幸运的是,AWS EKS提供了强大的控制平面日志(Control Plane Logging)功能,特别是其中的审计日志(Audit Logs),它能记录下对K8s API Server的每一次调用。今天,我们就来一步步了解如何利用它,揪出每一次高危操作,并设置实时告警。

image.png

核心原理:让K8s API Server成为我们的“告密者”

要理解如何监控,我们首先要明白kubectl命令的工作原理。其实,每一条kubectl命令,本质上都是向Kubernetes API Server发送的一个HTTP请求。

例如,当我们执行kubectl exec -it my-pod -- /bin/bash时,kubectl客户端实际上是向API Server发起了创建pods/exec子资源的请求。

我们的监控逻辑就是:

  1. 开启日志:在EKS集群上启用审计日志功能,让API Server把所有请求记录都发送到AWS CloudWatch Logs。
  2. 分析日志:审计日志是结构化的JSON格式,包含了请求者(user)、操作(verb)、目标资源(objectRef)等所有关键信息。
  3. 筛选关键行为:我们在海量的日志中,通过创建**指标筛选器(Metric Filter)**来精确匹配execport-forward这类操作。
  4. 实时告警:一旦匹配到这些行为,就触发CloudWatch告警(Alarm),通过SNS通知到我们。

image.png

整个流程清晰明了,接下来让我们进入实战环节。

实战指南:三步搭建我们的EKS操作“天眼”

前提条件:

  • 一个正在运行的EKS集群。
  • 安装并配置好AWS CLI,且拥有管理EKS集群的权限。

第一步:启用EKS审计日志

默认情况下,EKS控制平面日志是关闭的。我们需要通过AWS CLI手动开启它。我们只关心审计日志,所以只开启audit类型。

# 将 "your-cluster-name" 替换为我们的EKS集群名称
aws eks update-cluster-config \
    --name your-cluster-name \
    --logging '{"clusterLogging":[{"types":["audit"],"enabled":true}]}'

执行此命令后,AWS会更新我们的EKS集群配置。这可能需要几分钟时间。更新完成后,EKS会自动在CloudWatch中创建一个名为 /aws/eks/your-cluster-name/cluster 的日志组,所有审计日志都会被发送到这里。

实用建议:除了audit,EKS还支持apiauthenticator等日志类型。api记录了API服务器的请求和响应,但审计日志更侧重于安全审计,信息更精炼。对于此场景,audit是最佳选择。

第二步:分析日志并创建指标筛选器

现在,日志已经开始流入CloudWatch了。随便在一个Pod上执行一次exec操作:

# 确保我们有pod可以操作
kubectl run test-pod --image=nginx
kubectl exec -it test-pod -- echo "hello from exec"

然后去CloudWatch日志组,我们会找到类似下面的日志条目(已精简):

{
    "kind": "Event",
    "apiVersion": "audit.k8s.io/v1",
    "level": "Metadata",
    "verb": "create",
    "requestURI": "/api/v1/namespaces/default/pods/test-pod/exec?command=echo...&container=test-pod...",
    "user": {
        "username": "arn:aws:iam::123456789012:user/your-iam-user",
        "groups": ["system:masters", "system:authenticated"]
    },
    "objectRef": {
        "resource": "pods",
        "namespace": "default",
        "name": "test-pod",
        "subresource": "exec" // <-- 关键点!
    },
    ...
}

从日志中我们发现了关键信息:

  • 操作"verb": "create"execport-forward都是通过创建子资源实现的)
  • 识别符"objectRef": { "subresource": "exec" }"objectRef": { "subresource": "portforward" }

有了这个,我们就可以创建指标筛选器了。

  1. 导航到 CloudWatch -> 日志组,选择 /aws/eks/your-cluster-name/cluster

  2. 点击 “操作” -> “创建指标筛选器”

  3. “筛选模式” 中,输入以下表达式。这个表达式会匹配所有create操作的execport-forward事件:

    { ($.verb = "create") && (($.objectRef.subresource = "exec") || ($.objectRef.subresource = "portforward")) }
    
  4. 点击“下一步”,为该筛选器分配一个指标:

    • 筛选器名称HighRiskKubectlOperations
    • 指标命名空间EKS/Audit (自定义,方便归类)
    • 指标名称HighRiskOperationCount
    • 指标值1 (每次匹配到日志,指标值就+1)

第三步:创建告警

当指标创建成功后,我们就可以基于它来创建告警了。

  1. 在指标筛选器页面,找到刚创建的HighRiskKubectlOperations,点击右侧的 “创建警报”
  2. 配置告警条件:
    • 指标名称HighRiskOperationCount
    • 统计数据求和 (Sum)
    • 周期1 分钟
    • 条件大于 (>)
    • 阈值0 (意味着只要在1分钟内,发生至少1次高危操作,就告警)
  3. 配置操作:
    • 选择 “状态为ALARM” 时。
    • 选择一个现有的SNS主题,或创建一个新的。这个SNS主题可以配置为发送邮件、短信、调用Lambda或推送到Slack。

点击创建,大功告成!现在,只要有人在我们的集群上执行kubectl execport-forward,我们就会在1分钟内收到告警邮件。邮件中可以包含时间戳等信息,结合CloudWatch日志中的user字段,我们可以快速定位到是谁、在什么时间、对哪个Pod执行了高危操作。

结论与延伸

通过利用EKS审计日志和CloudWatch,我们以一种云原生的方式,为集群中最危险的操作安装了一个灵敏的“防盗铃”。这不仅满足了安全合规的要求,更重要的是,它将潜在的威胁从“暗处”拉到了“明处”,极大地提升了集群的整体安全性。

我们可以更进一步:

  • 细化告警:可以基于user.usernameobjectRef.namespace创建更精细的筛选器,例如只告警非白名单用户或在生产命名空间中的操作。
  • 日志归档与分析:将CloudWatch日志长期归档到S3,或使用Amazon Athena、OpenSearch进行更复杂的历史行为分析和可视化。
  • 自动化响应:通过Lambda函数订阅SNS通知,实现自动化响应,例如临时隔离Pod或向安全团队的IM工具发送详细的事件报告。

希望这篇文章能帮助大家更好地守护自己的EKS集群。安全无小事,从监控每一次高危操作开始!