10.6 项目实战:容器安全体系建设

预计阅读时间:18 分钟

📖 目录

学习目标

完成本项目后,你将能够:

  • 理解容器安全的威胁模型和防护原则
  • 使用 Trivy 配置镜像扫描并集成到 CI/CD
  • 使用 Falco 配置运行时监控和告警
  • 使用 Kyverno 实现 Kubernetes 安全策略
  • 使用 Cosign 实现镜像签名与验证
  • 使用 Docker Bench 进行安全基线审计
  • 建立完整的漏洞管理和事件响应流程

前置知识

开始本项目前,你需要掌握以下知识:

  • Docker 基础操作(镜像、容器、网络)
  • Kubernetes 基础概念(Pod、Deployment、Service)
  • Linux 命令行操作和 Shell 脚本基础
  • CI/CD 基本流程(如 Jenkins、GitHub Actions)
  • 基本的网络安全概念
环境要求
  • 操作系统:Ubuntu 24.04 LTS 或 CentOS 8+
  • Docker:24.0+
  • Kubernetes:1.28+(可使用 Minikube 或 Kind)
  • 磁盘空间:至少 20GB 可用
  • 内存:至少 4GB RAM

容器安全概述

安全威胁分析

容器环境面临多层次的安全威胁,理解这些威胁是构建安全体系的基础:

Trivy:Aqua Security 开源的漏洞扫描工具,支持容器镜像、文件系统和 Git 仓库的漏洞检测。Falco:CNCF 开源的运行时安全工具,通过分析系统调用来检测容器内的异常行为。Kyverno:Kubernetes 原生的策略引擎,用于验证、变异和生成 K8s 资源配置。Cosign:Sigstore 项目的容器镜像签名工具,用于验证镜像的完整性和来源。SBOM(Software Bill of Materials):软件物料清单,列出软件中包含的所有组件和依赖。CVSS(Common Vulnerability Scoring System):通用漏洞评分系统,用于评估漏洞的严重程度。

威胁层次威胁类型潜在影响
构建时镜像漏洞、恶意依赖供应链攻击
部署时配置错误、权限过宽容器逃逸
运行时异常行为、横向移动数据泄露
基础设施内核漏洞、网络攻击集群沦陷

安全体系架构

完整的容器安全体系分为三个层面:

构建时安全
    ├── 镜像扫描(Trivy)
    │   └── 检测 OS 和应用层漏洞
    ├── 最小化镜像
    │   └── 使用 distroless 或 alpine 基础镜像
    └── 镜像签名(Cosign)
        └── 验证镜像完整性和来源

运行时安全
    ├── 运行时监控(Falco)
    │   └── 检测异常系统调用和行为
    ├── 安全策略(Kyverno)
    │   └── 强制执行安全配置
    └── 资源限制
        └── CPU、内存、网络配额

审计与合规
    ├── 安全基线(Docker Bench)
    │   └── CIS Docker Benchmark 检查
    ├── 漏洞管理
    │   └── 生命周期跟踪和修复
    └── 事件响应
        └── 自动化检测与响应

安全原则

遵循以下原则可大幅降低容器安全风险:

  • 最小权限原则:容器以非 root 用户运行,只授予必要的 Linux capabilities
  • 最小攻击面:使用精简镜像,移除不必要的工具和 shell
  • 纵深防御:在多个层面实施安全控制,避免单点失败
  • 不可变基础设施:容器不应被修改,更新时部署新容器
  • 安全左移:在开发早期发现并修复安全问题

第一步:配置镜像扫描

安装 Trivy

Trivy 是 Aqua Security 开发的开源漏洞扫描工具,支持容器镜像、文件系统和 Git 仓库扫描。

# 添加 Trivy 仓库(Ubuntu/Debian)
sudo apt-get install wget apt-transport-https gnupg lsb-release
sudo mkdir -p /etc/apt/keyrings
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo tee /etc/apt/keyrings/trivy.asc > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/trivy.asc] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | \
    sudo tee /etc/apt/sources.list.d/trivy.list

# 安装 Trivy
sudo apt-get update
sudo apt-get install -y trivy

# 验证安装
trivy --version
# 输出示例: Version: 0.52.0

扫描容器镜像

# 扫描 Docker Hub 官方镜像
trivy image nginx:latest
# 输出示例:
# nginx:latest (debian 12.5)
# Total: 156 (UNKNOWN: 0, LOW: 85, MEDIUM: 45, HIGH: 22, CRITICAL: 4)

# 只显示高危和严重漏洞
trivy image --severity HIGH,CRITICAL nginx:latest

# 输出为 JSON 格式(用于自动化处理)
trivy image --format json --output result.json nginx:latest

# 扫描本地构建的镜像
docker build -t myapp:latest .
trivy image myapp:latest

# 扫描未推送的镜像(使用镜像 ID)
IMAGE_ID=$(docker images -q myapp:latest)
trivy image "$IMAGE_ID"

CI/CD 集成

将 Trivy 集成到 GitHub Actions 工作流中:

# .github/workflows/security-scan.yml
name: Container Security Scan

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  trivy-scan:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build Docker image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'

      - name: Upload Trivy scan results
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: 'trivy-results.sarif'

      - name: Fail on critical vulnerabilities
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          exit-code: '1'
          severity: 'CRITICAL'

漏洞管理策略

# 创建 Trivy 忽略文件(.trivyignore)
# 用于标记已评估为可接受的漏洞
# 格式:CVE-ID  # 理由
CVE-2024-12345  # 评估:仅影响测试代码,无生产风险
CVE-2024-67890  # 评估:上游已发布补丁,等待下一个版本

# 使用忽略文件扫描
trivy image --ignorefile .trivyignore nginx:latest

# 定期扫描脚本
#!/bin/bash
# scan-images.sh - 定期扫描所有运行中的容器镜像
set -e

LOG_FILE="/var/log/trivy-scan-$(date +%Y%m%d).log"

echo "=== Trivy 扫描开始: $(date) ===" | tee -a "$LOG_FILE"

# 获取所有运行中的容器镜像
for image in $(docker ps --format '{{.Image}}' | sort -u); do
    echo "扫描: $image" | tee -a "$LOG_FILE"
    trivy image --severity HIGH,CRITICAL \
        --format json \
        --output "/tmp/trivy-$(echo $image | tr ':' '_').json" \
        "$image" 2>&1 | tee -a "$LOG_FILE"
done

echo "=== 扫描完成: $(date) ===" | tee -a "$LOG_FILE"

第二步:配置运行时监控

安装 Falco

Falco 是 CNCF 开源的运行时安全工具,通过分析系统调用来检测异常行为。

# 添加 Falco 仓库
curl -fsSL https://falco.org/repo/falco-archive.key | gpg --dearmor | \
    sudo tee /usr/share/keyrings/falco-archive-keyring.gpg > /dev/null

echo "deb [signed-by=/usr/share/keyrings/falco-archive-keyring.gpg] https://dl.falco.org/packages/deb stable main" | \
    sudo tee /etc/apt/sources.list.d/falco.list

# 安装 Falco
sudo apt-get update
sudo apt-get install -y falco

# 验证安装
falco --version
# 输出示例: Falco version: 0.38.0

# 启动 Falco 服务
sudo systemctl enable falco
sudo systemctl start falco
sudo systemctl status falco

配置自定义规则

# /etc/falco/rules.d/custom-rules.yaml
# 自定义 Falco 规则

# 规则1:检测容器内执行 shell
- rule: Container Shell Access
  desc: Detect shell execution in container
  condition: >
    spawned_process and container and proc.name in (bash, sh, zsh, dash) and
    not proc.pname in (cron, supervisord)
  output: >
    Shell executed in container
    (user=%user.name container_id=%container.id container_name=%container.name
    shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
  priority: WARNING
  tags: [container, shell, mitre_execution]

# 规则2:检测敏感文件访问
- rule: Sensitive File Access in Container
  desc: Detect access to sensitive files
  condition: >
    open_read and container and
    (fd.name startswith /etc/shadow or
     fd.name startswith /etc/passwd or
     fd.name contains /proc/self/environ)
  output: >
    Sensitive file accessed in container
    (file=%fd.name user=%user.name container=%container.name
    command=%proc.cmdline)
  priority: CRITICAL
  tags: [container, filesystem, mitre_credential_access]

# 规则3:检测异常网络连接
- rule: Unexpected Outbound Connection
  desc: Detect outbound connections to non-standard ports
  condition: >
    outbound and container and not (fd.sport in (80, 443, 53, 8080, 8443))
  output: >
    Unexpected outbound connection
    (destination=%fd.rip:%fd.rport container=%container.name
    command=%proc.cmdline)
  priority: NOTICE
  tags: [container, network, mitre_command_and_control]

# 规则4:检测 Kubernetes API 访问
- rule: K8s API Access from Container
  desc: Detect container accessing Kubernetes API
  condition: >
    outbound and container and fd.sip = "10.96.0.1" and fd.sport = 443
  output: >
    K8s API access from container
    (container=%container.name command=%proc.cmdline)
  priority: WARNING
  tags: [container, k8s, mitre_discovery]

告警集成

# /etc/falco/falco.yaml 配置输出
# 输出到 Syslog
syslog_output:
  enabled: true
  facility: daemon
  priority: WARNING

# 输出到文件
file_output:
  enabled: true
  keep_alive: false
  filename: /var/log/falco/falco-events.json

# 输出到 HTTP(用于集成 SIEM)
http_output:
  enabled: false
  url: "http://siem-server:8080/api/events"
  user_agent: "falco/0.38.0"
  insecure: false
  ca_cert: ""
  ca_bundle: ""
  ca_path: ""
  mtls: false
  client_cert: ""
  client_key: ""
  echo: false
  compress_uploads: false
  keep_alive: false

# 输出到 gRPC(用于 Falco Sidekick)
grpc_output:
  enabled: false
  host: "0.0.0.0:5060"
  port: 5060

事件分析脚本

#!/bin/bash
# analyze-falco-events.sh - 分析 Falco 事件日志

LOG_FILE="/var/log/falco/falco-events.json"
REPORT_FILE="/var/log/falco/daily-report-$(date +%Y%m%d).txt"

echo "=== Falco 安全事件报告 ===" > "$REPORT_FILE"
echo "生成时间: $(date)" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"

# 统计各优先级事件数量
echo "--- 事件统计 ---" >> "$REPORT_FILE"
if [ -f "$LOG_FILE" ]; then
    echo "CRITICAL: $(grep -c '"priority":"CRITICAL"' "$LOG_FILE" 2>/dev/null || echo 0)" >> "$REPORT_FILE"
    echo "HIGH:     $(grep -c '"priority":"HIGH"' "$LOG_FILE" 2>/dev/null || echo 0)" >> "$REPORT_FILE"
    echo "WARNING:  $(grep -c '"priority":"WARNING"' "$LOG_FILE" 2>/dev/null || echo 0)" >> "$REPORT_FILE"
    echo "NOTICE:   $(grep -c '"priority":"NOTICE"' "$LOG_FILE" 2>/dev/null || echo 0)" >> "$REPORT_FILE"
else
    echo "日志文件不存在" >> "$REPORT_FILE"
fi

echo "" >> "$REPORT_FILE"
echo "--- 高危事件详情 ---" >> "$REPORT_FILE"

# 列出最近的 CRITICAL 事件
if [ -f "$LOG_FILE" ]; then
    tail -1000 "$LOG_FILE" | grep '"priority":"CRITICAL"' | \
        jq -r '"[%] \n  规则: \(.rule)\n  容器: \(.container.name)\n  用户: \(.user.name)\n  命令: \(.proc.cmdline)\n"' 2>/dev/null \
        >> "$REPORT_FILE"
fi

echo "" >> "$REPORT_FILE"
echo "=== 报告结束 ===" >> "$REPORT_FILE"

# 显示报告
cat "$REPORT_FILE"

第三步:配置安全策略

安装 Kyverno

Kyverno 是 Kubernetes 原生的策略引擎,可以验证、变异和生成 Kubernetes 资源配置。

# 使用 Helm 安装 Kyverno
helm repo add kyverno https://kyverno.github.io/kyverno/
helm repo update

# 创建命名空间
kubectl create namespace kyverno

# 安装 Kyverno
helm install kyverno kyverno/kyverno -n kyverno \
    --set admissionController.replicas=2 \
    --set backgroundController.replicas=1

# 验证安装
kubectl get pods -n kyverno
# 输出示例:
# NAME                                       READY   STATUS    RESTARTS   AGE
# kyverno-admission-controller-xxx           1/1     Running   0          2m
# kyverno-background-controller-xxx          1/1     Running   0          2m

创建安全策略

# policy-restrict-image-registries.yaml
# 限制镜像只允许从指定仓库拉取
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-image-registries
  annotations:
    policies.kyverno.io/title: Restrict Image Registries
    policies.kyverno.io/category: 最佳实践
    policies.kyverno.io/severity: high
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: validate-registries
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "镜像必须来自允许的仓库"
        pattern:
          spec:
            containers:
              - image: "docker.io/library/* | gcr.io/* | quay.io/*"

---
# policy-require-labels.yaml
# 要求所有 Pod 必须有特定标签
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-labels
  annotations:
    policies.kyverno.io/title: Require Labels
    policies.kyverno.io/category: 最佳实践
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: check-for-labels
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Pod 必须有 'app' 和 'environment' 标签"
        pattern:
          metadata:
            labels:
              app: "?*"
              environment: "?*"

---
# policy-restrict-hostpath.yaml
# 禁止使用 hostPath 卷
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-hostpath
  annotations:
    policies.kyverno.io/title: Restrict HostPath
    policies.kyverno.io/category: 安全
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: validate-hostpath
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "不允许使用 hostPath 卷"
        pattern:
          spec:
            =(volumes):
              - X(hostPath): "null"

测试策略

# 应用策略
kubectl apply -f policy-restrict-image-registries.yaml
kubectl apply -f policy-require-labels.yaml
kubectl apply -f policy-restrict-hostpath.yaml

# 查看策略状态
kubectl get clusterpolicy
# 输出示例:
# NAME                     VALIDATE-ACTION   BACKGROUND   READY
# restrict-image-registries Enforce          true         true
# require-labels           Enforce          true         true
# restrict-hostpath        Enforce          true         true

# 测试:创建不符合策略的 Pod(应该被拒绝)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: test-bad-pod
spec:
  containers:
  - name: nginx
    image: my-private-registry.com/nginx:latest
EOF
# 输出示例:
# Error from server: admission webhook "kyverno-resource-validating-webhook.kyverno.svc"
# denied the request: 镜像必须来自允许的仓库

# 测试:创建符合策略的 Pod(应该成功)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: test-good-pod
  labels:
    app: test
    environment: dev
spec:
  containers:
  - name: nginx
    image: docker.io/library/nginx:latest
EOF
# 输出示例:
# pod/test-good-pod created

# 清理测试资源
kubectl delete pod test-good-pod

策略管理

# 查看策略违规事件
kubectl get events -n kyverno --field-selector reason=PolicyViolation

# 查看特定策略的违规
kubectl get policyreport -A
kubectl get clusterpolicyreport

# 禁用特定策略(临时)
kubectl patch clusterpolicy restrict-hostpath --type merge \
    -p '{"spec":{"validationFailureAction":"Audit"}}'

# 删除策略
kubectl delete clusterpolicy restrict-hostpath

# 导出策略用于版本控制
kubectl get clusterpolicy restrict-image-registries -o yaml > backup-policy.yaml

第四步:配置镜像签名

安装 Cosign

Cosign 是 Sigstore 项目的一部分,用于容器镜像的签名和验证。

# 安装 Cosign
# 方法1:使用二进制安装
COSIGN_VERSION="v2.4.3"
wget -qO cosign "https://github.com/sigstore/cosign/releases/download/${COSIGN_VERSION}/cosign-linux-amd64"
chmod +x cosign
sudo mv cosign /usr/local/bin/

# 方法2:使用 Go 安装
go install github.com/sigstore/cosign/v2/cmd/cosign@latest

# 验证安装
cosign version
# 输出示例: v2.4.3

生成密钥对

# 生成密钥对(交互式,会提示输入密码)
cosign generate-key-pair
# 生成文件:
#   cosign.key  - 私钥(必须保护)
#   cosign.pub  - 公钥(可以公开)

# 使用环境变量非交互式生成(仅用于测试)
COSIGN_PASSWORD="your-secure-password" cosign generate-key-pair

# 保护私钥
chmod 600 cosign.key
# 将私钥存储在安全位置(如 Vault、AWS Secrets Manager)
# 绝不将私钥提交到 Git 仓库

# .gitignore 中添加
echo "cosign.key" >> .gitignore

签名镜像

# 登录容器仓库
docker login docker.io

# 推送镜像
docker tag myapp:latest docker.io/yourusername/myapp:latest
docker push docker.io/yourusername/myapp:latest

# 签名镜像
COSIGN_PASSWORD="your-secure-password" cosign sign \
    --key cosign.key \
    docker.io/yourusername/myapp:latest

# 签名带附件(如 SBOM)
cosign attach sbom --sbom sbom.json \
    --key cosign.key \
    docker.io/yourusername/myapp:latest

# 查看签名信息
cosign verify --key cosign.pub docker.io/yourusername/myapp:latest

验证签名

# 验证镜像签名
cosign verify --key cosign.pub docker.io/yourusername/myapp:latest
# 输出示例:
# Verification for docker.io/yourusername/myapp:latest --
# The following checks were performed:
#   - The cosign signature was verified using the public key
# ...

# 在 Kubernetes 中使用 Kyverno 强制签名验证
cat <<EOF | kubectl apply -f -
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: verify-image-signature
spec:
  validationFailureAction: Enforce
  background: false
  webhookTimeoutSeconds: 30
  rules:
    - name: check-image-signature
      match:
        any:
          - resources:
              kinds:
                - Pod
      verifyImages:
      - imageReferences:
          - "docker.io/yourusername/*"
        attestors:
        - entries:
          - keys:
              publicKeys: |-
                -----BEGIN PUBLIC KEY-----
                MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
                -----END PUBLIC KEY-----
            rekor:
              url: https://rekor.sigstore.dev
EOF

第五步:配置安全审计

运行 Docker Bench

Docker Bench for Security 是一个检查 Docker 部署最佳实践的脚本,基于 CIS Docker Benchmark。

# 运行 Docker Bench(使用官方容器)
docker run --rm --net host --pid host --userns host --cap-add audit_control \
    -e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
    -v /var/lib:/var/lib:ro \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /etc:/etc:ro \
    --label docker_bench_security \
    docker/docker-bench-security

# 输出示例:
# [INFO] 1 - Host Configuration
# [PASS] 1.1.1 - Ensure a separate partition for containers has been created
# [WARN] 1.1.2 - Ensure only trusted users are allowed to control Docker daemon
# [PASS] 1.1.3 - Ensure Docker daemon content trust is enabled
# ...

分析报告

# 保存详细报告
docker run --rm --net host --pid host --userns host --cap-add audit_control \
    -v /var/lib:/var/lib:ro \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    -v /etc:/etc:ro \
    -v /var/log:/var/log \
    docker/docker-bench-security -l /var/log/docker-bench.log

# 分析报告脚本
#!/bin/bash
# analyze-bench-report.sh

REPORT="/var/log/docker-bench.log"

echo "=== Docker Bench 安全分析报告 ==="
echo "生成时间: $(date)"
echo ""

# 统计结果
echo "--- 检查结果统计 ---"
echo "通过 (PASS):    $(grep -c '\[PASS\]' "$REPORT")"
echo "警告 (WARN):    $(grep -c '\[WARN\]' "$REPORT")"
echo "信息 (INFO):    $(grep -c '\[INFO\]' "$REPORT")"
echo "手动检查:       $(grep -c '\[NOTE\]' "$REPORT")"

echo ""
echo "--- 需要关注的警告 ---"
grep '\[WARN\]' "$REPORT" | head -20

修复常见问题

# 问题1:Docker daemon 启用 content trust
# 修复:设置环境变量
echo 'export DOCKER_CONTENT_TRUST=1' >> ~/.bashrc
source ~/.bashrc

# 问题2:限制容器使用过多资源
# 在 daemon.json 中配置
cat > /etc/docker/daemon.json <<EOF
{
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65536,
      "Soft": 32768
    }
  },
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF
sudo systemctl restart docker

# 问题3:启用审计日志
# 添加审计规则
cat > /etc/audit/rules.d/docker.rules <<EOF
-w /usr/bin/docker -p wa -k docker
-w /var/lib/docker -p wa -k docker
-w /etc/docker -p wa -k docker
-w /var/run/docker.sock -p wa -k docker
EOF
sudo augenrules --load

第六步:建立漏洞管理流程

漏洞分类

# 漏洞严重程度分类
# 基于 CVSS 评分和业务影响

# 严重 (CRITICAL) - 立即修复
# CVSS >= 9.0 或已知被利用
# 示例:远程代码执行、认证绕过

# 高危 (HIGH) - 24小时内修复
# CVSS 7.0-8.9
# 示例:权限提升、信息泄露

# 中危 (MEDIUM) - 7天内修复
# CVSS 4.0-6.9
# 示例:拒绝服务、跨站脚本

# 低危 (LOW) - 30天内修复
# CVSS < 4.0
# 示例:信息泄露、配置问题

修复优先级

#!/bin/bash
# prioritize-vulnerabilities.sh - 漏洞优先级排序

# 从 Trivy 报告中提取漏洞并排序
INPUT_FILE="$1"
OUTPUT_FILE="prioritized-$(date +%Y%m%d).csv"

echo "CVE ID,严重程度,受影响包,当前版本,修复版本,优先级" > "$OUTPUT_FILE"

# 解析 JSON 并按优先级排序
jq -r '
    .Results[]?.Vulnerabilities[]? |
    [.VulnerabilityID, .Severity, .PkgName, .InstalledVersion, .FixedVersion] |
    @csv
' "$INPUT_FILE" | sort -t',' -k2 -r >> "$OUTPUT_FILE"

echo "优先级报告已生成: $OUTPUT_FILE"

# 显示统计
echo ""
echo "=== 漏洞统计 ==="
echo "CRITICAL: $(grep -c 'CRITICAL' "$OUTPUT_FILE")"
echo "HIGH:     $(grep -c 'HIGH' "$OUTPUT_FILE")"
echo "MEDIUM:   $(grep -c 'MEDIUM' "$OUTPUT_FILE")"
echo "LOW:      $(grep -c 'LOW' "$OUTPUT_FILE")"

修复流程

# 标准修复流程
# 1. 识别漏洞
trivy image --severity HIGH,CRITICAL myapp:latest

# 2. 确定修复方案
# - 更新基础镜像版本
# - 更新受影响的包
# - 修改 Dockerfile 使用更新的版本

# 3. 修复 Dockerfile 示例
cat > Dockerfile.fixed <<EOF
# 使用精简基础镜像
FROM node:20-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:20-alpine
# 以非 root 用户运行
RUN addgroup -g 1001 -S appgroup && \
    adduser -S appuser -u 1001 -G appgroup

WORKDIR /app
COPY --from=builder /app/node_modules ./
COPY . .

# 设置文件所有权
RUN chown -R appuser:appgroup /app

USER appuser
EXPOSE 3000
CMD ["node", "server.js"]
EOF

# 4. 重建并验证
docker build -f Dockerfile.fixed -t myapp:fixed .
trivy image myapp:fixed

# 5. 更新部署
kubectl set image deployment/myapp myapp=myapp:fixed

第七步:配置事件响应

响应流程

# 事件响应流程
# 1. 检测 - 通过监控系统发现异常
# 2. 分析 - 确定事件范围和影响
# 3. 遏制 - 隔离受影响的容器
# 4. 修复 - 消除威胁并恢复服务
# 5. 复盘 - 分析根因并改进防护

# 自动响应脚本
#!/bin/bash
# incident-response.sh - 自动化事件响应

CONTAINER_NAME="$1"
ACTION="$2"

case "$ACTION" in
    isolate)
        echo "隔离容器: $CONTAINER_NAME"
        # 获取容器网络命名空间
        CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' "$CONTAINER_NAME")
        # 断开网络(通过 iptables)
        nsenter -t "$CONTAINER_PID" -n iptables -A INPUT -j DROP
        nsenter -t "$CONTAINER_PID" -n iptables -A OUTPUT -j DROP
        echo "容器已隔离"
        ;;
    snapshot)
        echo "创建容器快照"
        docker commit "$CONTAINER_NAME" "forensics/${CONTAINER_NAME}-$(date +%s)"
        docker save "forensics/${CONTAINER_NAME}-$(date +%s)" | \
            gzip > "/var/forensics/${CONTAINER_NAME}-$(date +%s).tar.gz"
        echo "快照已保存"
        ;;
    terminate)
        echo "终止容器"
        docker stop "$CONTAINER_NAME"
        docker rm "$CONTAINER_NAME"
        echo "容器已终止"
        ;;
    *)
        echo "用法: $0 <container> <isolate|snapshot|terminate>"
        ;;
esac

自动化响应

# 使用 Falco + Falcosidekick 实现自动化响应
# 安装 Falcosidekick
helm install falcosidekick falcosecurity/falcosidekick \
    --namespace falco \
    --set config.slack.webhookurl="https://hooks.slack.com/services/YOUR/WEBHOOK/URL" \
    --set config.slack.channel="#security-alerts"

# Falco 规则中配置响应动作
- rule: Detect Crypto Mining
  desc: Detect cryptocurrency mining activity
  condition: >
    spawned_process and container and
    (proc.name in (xmrig, minerd, cpuminer) or
     proc.cmdline contains "stratum+tcp")
  output: >
    Crypto mining detected (user=%user.name container=%container.name
    command=%proc.cmdline)
  priority: CRITICAL
  tags: [crypto, mitre_impact]
  actions:
    - tag_docker_container
    - kill_container

事后分析

# 事后分析报告模板
cat > incident-report-$(date +%Y%m%d).md <<EOF
# 安全事件报告

## 事件信息
- 发现时间: $(date)
- 影响容器: $CONTAINER_NAME
- 事件类型: [检测/分析/遏制/修复]

## 事件描述
[详细描述事件经过]

## 影响范围
- 受影响服务:
- 数据泄露风险:
- 业务中断时间:

## 根因分析
[分析事件发生的原因]

## 修复措施
1. 立即措施:
2. 长期改进:

## 经验教训
[总结可以改进的地方]

## 附件
- Falco 事件日志
- 容器取证快照
- 网络流量日志
EOF

验证安全体系

# 完整验证流程
echo "=== 容器安全体系验证 ==="

# 1. 验证镜像扫描
echo "--- 镜像扫描 ---"
trivy image --severity CRITICAL nginx:latest | head -20

# 2. 验证运行时监控
echo "--- 运行时监控 ---"
sudo systemctl status falco | grep "Active:"

# 3. 验证安全策略
echo "--- 安全策略 ---"
kubectl get clusterpolicy

# 4. 验证镜像签名
echo "--- 镜像签名 ---"
cosign verify --key cosign.pub docker.io/yourusername/myapp:latest

# 5. 验证安全基线
echo "--- 安全基线 ---"
docker run --rm --net host --pid host docker/docker-bench-security 2>&1 | grep -E "\[PASS\]|\[WARN\]"

echo "=== 验证完成 ==="

常见错误

错误原因解决方案
Trivy 扫描超时网络问题或镜像太大配置镜像仓库代理,使用 --timeout 参数
Falco 无法启动内核版本不支持升级内核或使用 Falco driver
Kyverno 策略不生效策略语法错误使用 kubectl describe clusterpolicy 检查
Cosign 签名失败密钥路径错误或密码错误检查密钥文件和环境变量
Docker Bench 报错权限不足确保以 root 权限运行

最佳实践

  • 镜像安全:使用官方基础镜像,定期扫描,保持最小化
  • 运行时安全:以非 root 用户运行,限制 capabilities
  • 网络隔离:使用 Kubernetes NetworkPolicy 限制 Pod 间通信
  • 密钥管理:使用 Kubernetes Secrets 或外部密钥管理系统
  • 日志审计:集中收集和分析安全日志
  • 持续监控:建立 7x24 安全监控机制
  • 定期演练:进行安全事件响应演练
  • 合规检查:定期运行安全基线检查

练习题

  1. 配置 Trivy 定时扫描任务,每天扫描所有运行中的容器
  2. 编写自定义 Falco 规则,检测容器内的异常文件修改
  3. 使用 Kyverno 创建策略,强制所有容器设置资源限制
  4. 建立镜像签名流程,确保生产环境只运行签名镜像
  5. 设计完整的安全事件响应流程文档

学习检查点

学完本章后,请检验自己是否掌握以下内容:

检查项自测问题验证方法
概念理解能用自己的话解释容器安全体系的三个层面和各工具职责尝试向他人讲解
命令操作能不查文档完成 Trivy 扫描、Falco 监控和镜像签名配置在终端实际执行
原理掌握能说出容器安全的构建时、运行时和审计时防护原理画出流程图
故障排查能独立排查容器安全策略导致应用部署失败的问题模拟故障并修复
最佳实践能说明为什么需要建立完整的容器安全事件响应流程对比不同方案

本章总结

本项目构建了完整的容器安全体系,涵盖构建时、运行时和审计三个层面的安全控制:

安全层面工具核心功能
构建时Trivy镜像漏洞扫描
构建时Cosign镜像签名与验证
运行时Falco异常行为检测
运行时Kyverno安全策略执行
审计Docker Bench安全基线检查

掌握这套安全体系的搭建和运维,是成为云原生安全工程师的重要一步。实际生产中还需结合组织的安全要求和合规标准进行定制。

延伸阅读

↑ 回到顶部