容器安全遥测归一化引擎

Kestrel

针对 MITRE ATT&CK T1059.013 — Container CLI/API 检测场景的轻量级管道处理器。 将 Kubernetes 审计日志与 Docker 事件归一化为统一的 model.Event JSONL 流, 适配 Kubernetes sidecar 部署。

3.6MB 二进制体积
0 外部依赖
32 测试用例
T1059.013 ATT&CK

架构设计

Kestrel 采用管道模式工作:stdin 接收 JSONL → 归一化为 model.Event → stdout 输出 JSONL,适合作为 Kubernetes sidecar 部署在检测管线前端。

text
原始遥测 (JSONL)          归一化事件 (JSONL)
     │                         │
     ▼                         ▼
┌──────────┐    ┌───────────────────────┐    ┌──────────┐
│  stdin   │───▶│  main.go (管道处理器)  │───▶│  stdout  │
└──────────┘    └───────────────────────┘    └──────────┘
                       │
                       ▼
              ┌──────────────────┐
              │  service.Sidecar  │
              │                   │
              │  ┌─────────────┐  │
              │  │ detectSource│  │  ← 推断 K8s audit / Docker
              │  └──────┬──────┘  │
              │         ▼         │
              │  ┌─────┐ ┌──────┐│
              │  │K8s  │ │Docker││  ← 各自的归一化器
              │  │Audit│ │Event ││
              │  └─────┘ └──────┘│
              │         │         │
              │         ▼         │
              │   model.Event     │
              └──────────────────┘

管道模式

stdin/stdout JSONL 流式处理,零缓冲,适配 Unix 管道组合与 K8s sidecar 部署。

零外部依赖

仅使用 Go 标准库,二进制 3.6MB,无第三方包,供应链安全。

多源归一化

K8s audit 与 Docker event 自动推断归一化,统一为 model.Event

检测管线

完整检测管线从原始遥测到 MITRE 映射共 8 个阶段,当前 Sidecar 归一化层已实现,后续 Detector、Correlator、Scorer 待实现。

text
RAW TELEMETRY → [SIDECAR] → NORMALIZED EVENT → SIGNAL → ACTIVITY → CONTEXT EVAL → RISK → FINDING → MITRE MAPPING
                 ✅ 已实现                                                                                   待实现
状态职责
Sidecar (internal/service/)已实现原始 JSON → model.Event 归一化
Detector (internal/engine/)待实现Event → Signal 信号提取
Correlator待实现Signal → Activity 事件关联
Scorer待实现Activity → Finding 风险评分

项目结构

项目遵循 Go 标准布局:internal/ 私有包,cmd/main.go 入口,test/ 测试,k8s/ 部署配置。

text
Kestrel/
├── main.go                          # 管道处理器入口 (stdin JSONL → stdout JSONL)
├── go.mod / go.sum
├── Makefile                         # 构建/测试/演示一站式工具
├── .gitignore
├── internal/
│   ├── config/                      # 配置管理
│   │   └── config.go                #   flag + 环境变量合并,校验与版本注入
│   ├── model/                       # 数据模型层
│   │   ├── action.go                #   动作类型 (container_exec, shell_spawn, ...)
│   │   ├── actor.go                 #   执行者 (身份类型: user/SA/node/anonymous)
│   │   ├── activity.go              #   活动 (关联事件的集合)
│   │   ├── context.go              #   上下文 (授权状态、环境标识)
│   │   ├── correlation_key.go       #   关联键 (ActorID + SourceIP + ClusterID + SessionID)
│   │   ├── event.go                 #   事件 (归一化后的安全事件)
│   │   ├── finding.go               #   检测结果 (严重度 + 置信度 + 证据)
│   │   ├── k8.go                    #   Kubernetes 集群信息
│   │   ├── network.go              #   网络元数据
│   │   ├── process.go              #   进程元数据
│   │   ├── signal.go               #   信号 (异常类型 + 权重 + 证据)
│   │   ├── source.go               #   事件来源
│   │   └── target.go               #   目标 (集群/命名空间/Pod/容器)
│   ├── service/                     # 遥测归一化层
│   │   ├── sidecar.go               #   入口: Sidecar.Process(raw, source)
│   │   ├── k8s_audit.go             #   K8s 审计日志归一化器
│   │   └── docker_event.go          #   Docker daemon 事件归一化器
│   └── utilities/                   # 工具库
│       └── logger.go                #   结构化日志器 (4 级别 + verbose + 字段)
├── k8s/                             # Kubernetes 部署配置
│   ├── namespace.yaml               #   命名空间 (prod + dev)
│   ├── configmap.yaml               #   配置映射 (集群 ID、日志级别)
│   ├── rbac.yaml                    #   ServiceAccount + ClusterRole/Role
│   ├── deployment.yaml              #   Deployment (prod: 3 副本 / dev: 1 副本)
│   ├── service.yaml                 #   Service (prod: ClusterIP / dev: NodePort)
│   ├── ingress.yaml                 #   Ingress + NetworkPolicy
│   ├── test-target.yaml             #   测试目标 Pod (Gin 应用)
│   └── kustomization.yaml           #   Kustomize 入口
├── scripts/                         # 自动化脚本
│   ├── simulate.sh                  #   一键全场景模拟
│   ├── e2e-setup.sh                 #   e2e 环境准备
│   ├── e2e-real.sh                  #   e2e 真实测试
│   └── audit-policy.yaml            #   K8s 审计策略
└── test/
    ├── sidecar_test.go             # 归一化器单元测试 (12 个用例)
    ├── exec_attack_test.go          # exec 攻击测试方法论 (20 场景)
    ├── e2e_real_test.go             # e2e 真实场景测试
    └── attack_test.go              # 集成安全测试套件 (12 类攻击)

快速开始

三步上手:构建、演示、测试。所有操作通过 Makefile 一键执行。

1. 构建

bash
make build    # 编译到 bin/kestrel

2. 演示

bash
make demo      # 内置演示数据,verbose 模式

3. 测试

bash
make test      # 运行全部测试
make vet       # 静态分析
make lint      # golangci-lint (需安装)

推荐:使用 make simulate

一键执行 6 个阶段并生成技术化表格报告,详见一键全场景模拟章节。

命令行配置

配置通过 internal/config/config.go 管理,合并命令行参数与环境变量,包含校验与版本注入。

命令行参数

参数说明默认值
-cluster-id集群标识符环境变量 KESTREL_CLUSTER_ID
-vverbose 模式,输出 DEBUG 级别日志false
-log-format日志格式(text / json)text

环境变量

变量说明
KESTREL_CLUSTER_ID集群标识符,注入到所有归一化事件中

版本注入

版本信息通过 ldflags 在构建时注入:-ldflags '-X kestrel/internal/config.Version=v1.0.0'

使用方式

Kestrel 是管道处理器,通过 stdin 接收 JSONL 输入,stdout 输出归一化后的 model.Event JSONL。

从文件处理

bash
cat audit.log | ./bin/kestrel -cluster-id prod-eu-west > events.jsonl

实时流处理

bash
kubectl audit-stream | ./bin/kestrel -cluster-id prod-eu-west | detector

Docker 事件流

bash
docker events --format '{{json .}}' | ./bin/kestrel -cluster-id docker-host-01

Verbose 模式

bash
echo '{"auditID":"..."}' | ./bin/kestrel -cluster-id dev-cluster -v

信号处理

支持 SIGINT(Ctrl+C)和 SIGTERM 优雅关停,收到信号后停止读取新输入,输出统计后退出。

输出示例

归一化后的 model.Event JSON 结构,包含完整的 Actor、Action、Target、Source、Metadata 字段。

json
{
  "id": "audit-001",
  "timestamp": "2026-08-14T03:00:00Z",
  "actor": {
    "user_id": "",
    "username": "system:anonymous",
    "source_ip": "203.0.113.50",
    "user_agent": "kubectl/v1.28.0",
    "service_account": "",
    "identity_type": "anonymous"
  },
  "action": {
    "type": "container_exec",
    "command": "/bin/sh -c cat /etc/passwd",
    "interactive": true
  },
  "target": {
    "cluster_id": "prod-eu-west",
    "namespace": "production",
    "pod_id": "",
    "pod_name": "payment-svc",
    "container_id": "",
    "container_name": ""
  },
  "source": {
    "ip": "203.0.113.50",
    "port": 0,
    "hostname": "",
    "service": "kubectl/v1.28.0"
  },
  "metadata": {
    "audit_id": "audit-001",
    "audit_stage": "ResponseComplete",
    "environment": "production",
    "response_code": "200",
    "source_type": "k8s_audit",
    "subresource": "exec",
    "verb": "create"
  }
}

Kubernetes 部署

通过 Kustomize 一键应用所有配置,生产环境 3 副本 + ClusterIP + TLS Ingress + NetworkPolicy。

bash
# 应用全部配置(Kustomize)
kubectl apply -k k8s/

# 或单独应用
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/rbac.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml

生产环境配置特点

  • 3 副本 RollingUpdate(maxSurge=1, maxUnavailable=0)
  • ClusterIP Service + TLS Ingress(速率限制 + 安全头注入)
  • NetworkPolicy(仅允许 ingress-nginx 和 kube-system 入站)
  • ClusterRole 绑定(全局审计读取权限)
  • 资源限制: CPU 100m-500m / Memory 64Mi-256Mi

开发环境

bash
# 开发环境使用 dev 命名空间
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/rbac.yaml
kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml

# NodePort 暴露到 30080
minikube service kestrel-sidecar -n kestrel-dev

安全配置基线

所有环境共享的安全基线,遵循 Kubernetes 安全最佳实践。

配置项说明
runAsNonRoottrue禁止 root 运行
runAsUser1000非特权用户
readOnlyRootFilesystemtrue只读文件系统
allowPrivilegeEscalationfalse禁止提权
capabilities.dropALL丢弃所有 Linux capabilities
seccompProfileRuntimeDefault默认 seccomp 配置

遥测来源 — Kubernetes 审计日志

从 K8s API Server 审计日志接收 container/execcontainer/attachcontainer/portforward 调用。

提取字段映射

  • auditIDEvent.ID
  • stageTimestampEvent.Timestamp
  • user.username + groups → Actor.IdentityType(anonymous / service_account / node / user)
  • requestURI 查询参数 → Action.Command(多命令拼接)
  • objectRef.subresourceAction.Type(exec → ContainerExec)
  • sourceIPs[0]Actor.SourceIP
  • responseStatus.code → 403/401 标记为 denied
  • objectRef.namespaceTarget.Namespace + 环境推断

遥测来源 — Docker Daemon 事件

从 Docker daemon /events 流接收 exec_createexec_startattach 事件。

提取字段映射

  • Actor.IDTarget.ContainerID
  • Actor.Attributes["name"]Target.ContainerName
  • Actor.Attributes["image"]Metadata["image"]
  • Time / TimeNanoEvent.Timestamp
  • 缺少用户身份 → 保守默认 anonymous

身份分类

根据 K8s 用户名模式自动推断身份类型,影响后续检测器的告警阈值。

用户名模式身份类型说明
system:anonymousanonymous高警觉 匿名访问
system:serviceaccount:{ns}:{name}service_account提取 SA 名称
system:node:{name}node节点身份
其他user普通用户

命令提取

K8s audit 的 requestURI 带有查询参数,归一化时自动 URL 解码并拼接为完整命令字符串。

text
# 原始 requestURI
/api/v1/namespaces/default/pods/foo/exec?command=/bin/sh&command=-c&command=cat%20%2Fetc%2Fpasswd

# 归一化后 Action.Command
/bin/sh -c cat /etc/passwd

被拒绝的 exec

403/401 响应仍然被归一化,标记 metadata["denied"]=true。被拒绝的执行尝试本身是有价值的检测信号。

检测价值

被拒绝的 exec 请求往往代表攻击者在试探边界,是 MITRE ATT&CK 检测的重要信号源。

一键全场景模拟 (make simulate)

make simulate 是最推荐的一键式测试入口,自动执行 6 个阶段并生成技术化表格报告。

bash
make simulate         # 全自动:静态检查 + 构建 + 单元测试 + 演示 + e2e + 集成测试
make simulate-quick   # 快速模式:跳过 Minikube 部分,3 秒跑完

6 个执行阶段

阶段命令依赖说明
1/6 静态检查go vet ./...静态分析
2/6 构建go build -o bin/kestrel .编译二进制
3/6 单元测试4 项子测试归一化器 + exec 攻击方法论
4/6 演示模式cat demo.jsonl | ./bin/kestrel -v构建产物4 条样本归一化
5/6 e2e 真实测试go test -tags e2e ./test/Minikube + 审计日志真实 kubectl exec 场景
6/6 集成安全测试go test -tags integration ./test/Minikube12 类 Web 攻击模拟

输出报告示例

text
测试明细 (Test Details)
+----+--------------------------------------+--------+----------+----------+------------------------------------------+
| #  | 测试项 (Test Name)                   | 结果   | 耗时     | 日志行数 | 说明 (Detail)                            |
+----+--------------------------------------+--------+----------+----------+------------------------------------------+
| 1  | go vet ./...                         | [PASS] | 0s       |        0 | 耗时 0s, 日志 0 行                       |
| 2  | go build                             | [PASS] | 0s       |        0 | 耗时 0s, 日志 0 行                       |
| 3  | sidecar_test (12 用例)              | [PASS] | 1s       |        3 | 耗时 1s, 日志 3 行                       |
| 4  | exec_attack (20 场景)               | [PASS] | 0s       |        1 | 耗时 0s, 日志 1 行                       |
| 7  | demo 归一化                          | [PASS] | 0s       |        0 | 输出 4 个事件, 退出码 0                  |
+----+--------------------------------------+--------+----------+----------+------------------------------------------+

统计 (Statistics)
+--------------------------+-------------------+
| 指标 (Metric)            | 值 (Value)        |
+--------------------------+-------------------+
| 通过率 (Pass Rate)       | 77.8%             |
| 总耗时 (Total Duration)  | 3s                |
+--------------------------+-------------------+

单元测试

bash
make test
# 或
go test ./test/ -v

覆盖 12 个用例:匿名 exec(真阳性)、SRE 调试(假阳性)、服务账号身份、被拒绝的 exec、批量摄入、Docker exec_create、Docker attach、未知来源错误、畸形 JSON、空载荷、节点身份、多命令提取。

exec 攻击测试方法论

exec_attack_test.go 实现 5 层测试方法论,覆盖 20 个攻击场景。

bash
go test ./test/ -run TestExecAttackScenarios -v      # 20 个场景
go test ./test/ -run TestExecAttackSuccessCriteria   # 6 个质量门禁(CI 用)
go test ./test/ -run TestExecAttackReport -v         # 汇总报告 + 缓解建议
类别场景数说明
K8s exec 向量12匿名入侵、SA 滥用、反向 Shell、C2 外联、凭证窃取等
Docker exec 向量3exec_create、exec_start、attach
健壮性测试5URL 编码绕过、空命令、畸形 JSON、空载荷

e2e 真实场景测试

e2e_real_test.go 在真实 Minikube 集群中执行真实 kubectl exec 命令,捕获审计日志并验证归一化。

bash
# 1. 准备环境(启动带审计日志的 Minikube)
make e2e-setup
# 或 ./scripts/e2e-setup.sh --force

# 2. 运行 e2e 测试
make e2e
# 或 go test -tags e2e ./test/ -run TestE2ERealExec -v
场景 ID命令严重度
E2E-001whoami
E2E-002/bin/sh -c cat /etc/passwd
E2E-003/bin/sh -c id
E2E-004ls /
E2E-005/bin/sh -c env

集成安全测试

集成测试使用 //go:build integration 构建标签,需要运行中的 Minikube 集群。

bash
# 完整安全测试套件(需要 Minikube 运行中)
go test -tags integration ./test/ -v

# 仅运行安全评估
go test -tags integration ./test/ -run TestAttackSuite/Security_Assessment -v

# 仅运行边缘场景测试
go test -tags integration ./test/ -run "TestLargePayload|TestConcurrentRequests|TestMalformedJSON" -v

# 指定应用地址(跳过 Minikube 自动发现)
TEST_APP_URL=http://localhost:8080 go test -tags integration ./test/ -run TestSecurity -v

安全测试覆盖

测试类别载荷数严重度检测内容
路径穿越5../ 序列、URL 编码绕过
命令注入8Shell 元字符、子命令注入
SSRF8云元数据端点、内网扫描
SQL 注入6布尔注入、UNION、堆叠查询
认证绕过10请求头伪造、路径绕过
跨站脚本6反射型 XSS、事件处理器注入
开放重定向5外部域名跳转、协议注入
目录列表8敏感文件暴露、.git/.env
安全响应头6HSTS、CSP、X-Frame-Options
HTTP 方法篡改9TRACE/PROPFIND/CONNECT
HTTP 参数污染4重复参数绕过
Host 头注入4恶意 Host 反射

设计原则

  1. 归一化 ≠ 检测 — Sidecar 只负责把原始遥测变成干净的 model.Event,不生成信号或告警
  2. Denied exec 仍记录 — 被拒绝的尝试是宝贵的检测信号
  3. Docker 缺身份 → 保守匿名 — 让检测器以更高警觉评估
  4. 零外部依赖 — 仅用 Go 标准库
  5. 管道模式 — stdin/stdout JSONL,适合 Kubernetes sidecar 部署
  6. 优雅关停 — SIGINT/SIGTERM 信号响应,不丢正在处理的事件

MITRE ATT&CK 映射

Kestrel 针对 MITRE ATT&CK T1059.013 — Container CLI/API 检测场景设计。

字段
TechniqueT1059.013 — Container CLI/API
Detection StrategyDET0083
AnalyticAN0233

Kestrel — 容器安全遥测归一化引擎

针对 MITRE ATT&CK T1059.013 检测场景