← 返回首页
🔧

镜像扫描:容器漏洞管理

📂 devops ⏱ 3 min 567 words

镜像扫描:容器漏洞管理

什么是镜像扫描

镜像扫描是分析容器镜像中已知漏洞的过程。通过扫描镜像中的软件包和依赖项,识别CVE漏洞和配置问题,帮助团队在部署前修复安全问题。

扫描工具

Trivy

# 安装Trivy
sudo apt-get install trivy

# 扫描镜像
trivy image nginx:latest

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

# 输出JSON格式
trivy image -f json -o results.json nginx:latest

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

# 忽略未修复的漏洞
trivy image --ignore-unfixed nginx:latest

Snyk

# 安装Snyk
npm install -g snyk

# 认证
snyk auth

# 扫描镜像
snyk container test nginx:latest

# 监控持续扫描
snyk container monitor nginx:latest --file=Dockerfile

# 修复漏洞
snyk container fix nginx:latest

Grype

# 安装Grype
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s

# 扫描镜像
grype nginx:latest

# 只显示高危漏洞
grype nginx:latest --fail-on high

# 输出JSON格式
grype nginx:latest -o json > results.json

CI/CD集成

GitHub Actions

# .github/workflows/image-scan.yml
name: Container Image Scan

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

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Build 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: 'table'
          exit-code: '1'
          severity: 'CRITICAL,HIGH'
          ignore-unfixed: true
      
      - name: Upload scan results
        uses: actions/upload-artifact@v3
        if: always()
        with:
          name: scan-results
          path: trivy-results.sarif

GitLab CI

# .gitlab-ci.yml
image-scan:
  stage: test
  image: docker:latest
  services:
    - docker:dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: false

Jenkins Pipeline

// Jenkinsfile
pipeline {
    agent any
    
    stages {
        stage('Build') {
            steps {
                sh 'docker build -t myapp:${BUILD_NUMBER} .'
            }
        }
        
        stage('Security Scan') {
            steps {
                sh 'trivy image --exit-code 1 --severity HIGH,CRITICAL myapp:${BUILD_NUMBER}'
            }
        }
        
        stage('Push') {
            when {
                expression { currentBuild.resultIsBetterOrEqualTo('SUCCESS') }
            }
            steps {
                sh 'docker push registry.example.com/myapp:${BUILD_NUMBER}'
            }
        }
    }
    
    post {
        always {
            archiveArtifacts artifacts: 'trivy-results.json'
        }
    }
}

扫描策略

配置策略

# scan-policy.yaml
scan_policy:
  triggers:
    - on_push: true
    - on_pr: true
    - scheduled: "0 2 * * *"  # 每天凌晨2点
  
  severity_levels:
    - CRITICAL
    - HIGH
  
  ignore_unfixed: true
  
  timeout: "30m"
  
  exclusions:
    - cve: "CVE-2021-12345"
      reason: "已评估为误报"
      expires: "2024-12-31"
    
    - package: "libssl1.1"
      reason: "内部补丁已应用"

基础镜像管理

# base-images.yaml
base_images:
  - name: "alpine"
    version: "3.18"
    scan_frequency: "weekly"
    auto_update: true
  
  - name: "python"
    version: "3.11-slim"
    scan_frequency: "weekly"
    auto_update: false
  
  - name: "node"
    version: "20-alpine"
    scan_frequency: "weekly"
    auto_update: true

漏洞管理

漏洞分类

# vulnerability-classification.yaml
severity:
  CRITICAL:
    description: "严重漏洞"
    cvss_range: "9.0-10.0"
    response_time: "24小时"
    action: "立即修复"
  
  HIGH:
    description: "高危漏洞"
    cvss_range: "7.0-8.9"
    response_time: "7天"
    action: "尽快修复"
  
  MEDIUM:
    description: "中危漏洞"
    cvss_range: "4.0-6.9"
    response_time: "30天"
    action: "计划修复"
  
  LOW:
    description: "低危漏洞"
    cvss_range: "0.1-3.9"
    response_time: "90天"
    action: "评估后决定"

修复流程

#!/bin/bash
# fix-vulnerabilities.sh

IMAGE=$1
SEVERITY=$2

# 扫描并获取漏洞列表
echo "扫描镜像: $IMAGE"
VULNS=$(trivy image -f json $IMAGE | jq -r '.Results[].Vulnerabilities[] | select(.Severity == "'$SEVERITY'") | .VulnerabilityID')

# 逐个修复
for vuln in $VULNS; do
  echo "修复漏洞: $vuln"
  
  # 检查是否有可用修复
  FIX_AVAILABLE=$(trivy image -f json $IMAGE | jq -r '.Results[].Vulnerabilities[] | select(.VulnerabilityID == "'$vuln'") | .FixedVersion')
  
  if [ -n "$FIX_AVAILABLE" ]; then
    echo "有可用修复: $FIX_AVAILABLE"
    # 更新包版本
    # docker run --rm -it $IMAGE apk upgrade --available
  else
    echo "暂无可用修复,添加到忽略列表"
  fi
done

监控和报告

Prometheus监控

# prometheus-rules.yaml
groups:
  - name: image-scan-alerts
    rules:
      - alert: CriticalVulnerabilityFound
        expr: trivy_vulnerabilities{severity="CRITICAL"} > 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "发现严重漏洞"
          description: "镜像 {{ $labels.image }} 发现 {{ $value }} 个严重漏洞"
      
      - alert: HighVulnerabilityCount
        expr: trivy_vulnerabilities{severity="HIGH"} > 10
        for: 1h
        labels:
          severity: warning
        annotations:
          summary: "高危漏洞数量过多"
          description: "镜像 {{ $labels.image }} 有 {{ $value }} 个高危漏洞"

生成报告

#!/bin/bash
# generate-report.sh

REPORT_DIR="/reports/$(date +%Y%m%d)"
mkdir -p $REPORT_DIR

# 扫描所有生产镜像
for image in $(kubectl get pods -n production -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u); do
  echo "扫描: $image"
  trivy image -f json -o "$REPORT_DIR/$(echo $image | tr '/:' '_').json" $image
done

# 生成汇总报告
echo "生成汇总报告..."
trivy image --format table $(kubectl get pods -n production -o jsonpath='{.items[*].spec.containers[*].image}' | tr ' ' '\n' | sort -u) > "$REPORT_DIR/summary.txt"

最佳实践

  1. 早期扫描: 在CI/CD流水线早期阶段进行扫描
  2. 定期扫描: 定期重新扫描已部署的镜像
  3. 策略执行: 设置扫描失败阻止部署
  4. 漏洞跟踪: 建立漏洞跟踪和修复流程
  5. 基础镜像更新: 定期更新基础镜像
  6. 最小化镜像: 使用最小化基础镜像减少攻击面