Shell脚本如何扫描容器镜像漏洞

wen 实用脚本 1

本文目录导读:

Shell脚本如何扫描容器镜像漏洞

  1. 使用 Trivy(推荐)
  2. 使用 Grype
  3. 使用 Docker Scout(Docker Desktop 内置)
  4. 综合扫描脚本(带CI/CD集成)
  5. 使用方式
  6. 重要提示

在Shell脚本中扫描容器镜像漏洞,通常需要借助第三方的漏洞扫描工具,以下是几种常见的方法和对应的脚本示例:

使用 Trivy(推荐)

Trivy 是最流行的开源容器漏洞扫描工具之一。

安装 Trivy

# macOS
brew install trivy
# Linux
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh
# Docker 方式运行
docker run aquasec/trivy --help

扫描脚本示例

#!/bin/bash
# 扫描单个镜像
scan_image() {
    local image_name="$1"
    echo "扫描镜像: $image_name"
    # Trivy 扫描,输出 JSON 格式
    trivy image --format json --output "${image_name//\//_}_scan.json" "$image_name"
    # 检查是否有严重漏洞
    trivy image --severity CRITICAL,HIGH --exit-code 1 "$image_name"
    if [ $? -eq 1 ]; then
        echo "警告: 发现严重或高危漏洞!"
        return 1
    fi
    return 0
}
# 批量扫描多个镜像
scan_images() {
    local images=("$@")
    local failed=0
    for image in "${images[@]}"; do
        if ! scan_image "$image"; then
            failed=$((failed + 1))
        fi
    done
    echo "扫描完成: $failed 个镜像存在漏洞"
    return $failed
}
# 使用示例
images=(
    "nginx:latest"
    "node:14-alpine"
    "python:3.9-slim"
)
scan_images "${images[@]}"

使用 Grype

Grype 是 Anchore 的开源漏洞扫描工具。

安装 Grype

# macOS
brew install grype
# Linux
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin

扫描脚本

#!/bin/bash
scan_with_grype() {
    local image="$1"
    local output_file="${image//\//_}_grype_scan.json"
    echo "使用 Grype 扫描: $image"
    # JSON 格式输出
    grype "$image" -o json > "$output_file"
    # 仅显示严重漏洞
    echo "严重漏洞:"
    cat "$output_file" | jq '.matches[] | select(.vulnerability.severity == "Critical") | {package: .artifact.name, vulnerability: .vulnerability.id}'
    # 检查并返回退出码
    grype "$image" --fail-on Critical --quiet
    return $?
}
# 使用示例
if scan_with_grype "nginx:latest"; then
    echo "未发现严重漏洞"
else
    echo "发现严重漏洞,请检查报告"
fi

使用 Docker Scout(Docker Desktop 内置)

#!/bin/bash
# 需要 Docker Desktop 4.17+
scan_with_docker_scout() {
    local image="$1"
    echo "使用 Docker Scout 扫描: $image"
    # 登录 Docker Hub(如果需要)
    # docker login
    # 启用 Docker Scout
    docker scout enable
    # 扫描镜像
    docker scout quickview "$image"
    # 获取详细报告
    docker scout recommendations "$image"
    # 比较镜像
    docker scout compare "$image" --to "nginx:1.25-alpine"
}
# 使用示例
scan_with_docker_scout "nginx:latest"

综合扫描脚本(带CI/CD集成)

#!/bin/bash
set -euo pipefail
# 配置
SCANNER="trivy"  # trivy, grype, or docker-scout
SEVERITY_THRESHOLD="CRITICAL,HIGH"
EXIT_ON_FINDINGS=true
REPORT_DIR="./security_reports"
# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# 检查工具安装
check_tool() {
    if ! command -v "$1" &> /dev/null; then
        log_error "$1 未安装"
        exit 1
    fi
}
# 创建报告目录
setup_reports() {
    mkdir -p "$REPORT_DIR"
    local timestamp=$(date +%Y%m%d_%H%M%S)
    REPORT_FILE="$REPORT_DIR/scan_report_$timestamp.json"
}
# 使用 Trivy 扫描
trivy_scan() {
    local image="$1"
    local image_safe="${image//\//_}"
    log_info "开始 Trivy 扫描: $image"
    # 完整扫描并输出 JSON
    trivy image --format json \
                --severity "$SEVERITY_THRESHOLD" \
                --output "$REPORT_DIR/${image_safe}_trivy.json" \
                "$image" 2>/dev/null
    # 快速检查漏洞
    local vuln_count=$(trivy image --severity "$SEVERITY_THRESHOLD" \
                                    --exit-code 0 \
                                    --quiet \
                                    "$image" 2>/dev/null | grep -c "Total:")
    echo "$vuln_count"
}
# 生成HTML报告
generate_html_report() {
    local image="$1"
    local image_safe="${image//\//_}"
    local html_file="$REPORT_DIR/${image_safe}_report.html"
    cat > "$html_file" << EOF
<!DOCTYPE html>
<html>
<head>容器漏洞扫描报告 - $image</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        h1 { color: #333; }
        .critical { color: red; }
        .high { color: orange; }
        .medium { color: yellow; }
        .low { color: green; }
    </style>
</head>
<body>
    <h1>扫描报告: $image</h1>
    <p>扫描时间: $(date)</p>
    <h2>漏洞摘要</h2>
    <pre>$(cat "$REPORT_DIR/${image_safe}_trivy.json" | python3 -m json.tool 2>/dev/null || cat "$REPORT_DIR/${image_safe}_trivy.json")</pre>
</body>
</html>
EOF
    log_info "HTML报告已生成: $html_file"
}
# 清理函数
cleanup() {
    log_info "清理临时文件..."
    # 可以在这里添加清理逻辑
}
# 主函数
main() {
    local images=("$@")
    if [ ${#images[@]} -eq 0 ]; then
        log_error "请提供要扫描的镜像名称"
        echo "用法: $0 <镜像1> [镜像2] ..."
        exit 1
    fi
    # 设置清理陷阱
    trap cleanup EXIT
    # 检查工具
    check_tool "$SCANNER"
    setup_reports
    local total_vulns=0
    local failed_images=0
    for image in "${images[@]}"; do
        echo -e "\n${YELLOW}═══════════════════════════════════════${NC}"
        log_info "扫描镜像: $image"
        echo -e "${YELLOW}═══════════════════════════════════════${NC}\n"
        # 执行扫描
        if [ "$SCANNER" = "trivy" ]; then
            vuln_count=$(trivy_scan "$image")
            if [ "$vuln_count" -gt 0 ] && [ "$EXIT_ON_FINDINGS" = true ]; then
                log_warn "发现 $vuln_count 个漏洞"
                generate_html_report "$image"
                failed_images=$((failed_images + 1))
            else
                log_info "未发现漏洞"
            fi
        fi
        total_vulns=$((total_vulns + vuln_count))
    done
    # 输出总结
    echo -e "\n${YELLOW}═══════════════════════════════════════${NC}"
    log_info "扫描完成"
    echo "扫描镜像数: ${#images[@]}"
    echo "存在漏洞的镜像数: $failed_images"
    echo "总漏洞数: $total_vulns"
    echo "报告位置: $REPORT_DIR"
    echo -e "${YELLOW}═══════════════════════════════════════${NC}"
    # 返回非零退出码表示有漏洞
    if [ "$failed_images" -gt 0 ] && [ "$EXIT_ON_FINDINGS" = true ]; then
        exit 1
    fi
}
# 执行主函数
main "$@"

使用方式

基本用法

# 扫描单个镜像
./scan.sh nginx:latest
# 扫描多个镜像
./scan.sh nginx:latest node:14-alpine python:3.9
# 忽略漏洞继续执行
./scan.sh --no-fail nginx:latest

CI/CD 集成示例 (GitLab CI)

container-scan:
  stage: test
  image: aquasec/trivy:latest
  script:
    - trivy image --severity CRITICAL,HIGH --exit-code 1 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    - main

重要提示

  1. 更新漏洞数据库:定期更新扫描工具的漏洞数据库

    trivy image --update  # 或
    trivy image --cache-backend redis://localhost:6379
  2. 性能考虑:大规模扫描时考虑使用缓存和并行处理

  3. 权限管理:确保脚本有适当的执行权限

    chmod +x scan.sh
  4. 结果处理:根据业务需求决定如何处理发现的漏洞(阻塞发布、记录报警等)

这些脚本提供了完整的容器漏洞扫描解决方案,可以根据具体需求进行调整和扩展。

抱歉,评论功能暂时关闭!