【云原生安全篇】Trivy助力离线Harbor漏洞扫描实践

目录

❤️ 摘要: 在云原生环境中,容器镜像的安全性至关重要。作为一个强大的、轻量级的开源漏洞扫描工具,Trivy 能为Harbor容器镜像仓库提供了安全扫描和扫描结果可视化等功能。然而,在一些网络隔离的环境中,Harbor 的在线扫描功能可能无法使用。本文将介绍如何通过 Trivy 实现 离线 Harbor 漏洞扫描,并详细展示如何使用 Trivy 结合 Harbor,在离线环境中保护镜像安全。


💯 本文关联文章:


1 概念

1.1 为什么需要离线漏洞扫描

在一些安全性要求高的企业和政府单位环境中,网络出于安全原因会受到限制,可能无法连接到互联网。特别是在敏感业务的生产环境中,Harbor 镜像仓库被隔离在内部网络中,无法直接与在线漏洞扫描服务通信。

在这种情况下,使用 Trivy 的 离线扫描 功能,可以在不访问互联网的前提下,保持对镜像的高效漏洞扫描,确保容器的安全性。

1.2 Trivy和Harbor 简介

Trivy

Trivy 是由 Aqua Security 开发的开源安全扫描工具,能够扫描容器镜像、文件系统、基础设施即代码(IaC)等对象中的已知漏洞。Trivy 提供了快速、准确的扫描结果,帮助开发人员在开发早期识别潜在的安全风险。

Trivy 有以下几个主要特性:

  • 快速扫描:支持高效的漏洞数据库更新。
  • 丰富的漏洞检测:支持扫描操作系统漏洞、第三方库漏洞(如 Java、Node.js 等)以及错误配置。
  • 离线模式:支持离线使用和数据库更新,这对于网络受限的环境非常有用。

Harbor

Harbor 是一个开源的企业级云原生镜像仓库,它不仅可以存储和分发 Docker 镜像,还提供了镜像复制、权限控制、镜像签名、漏洞扫描等功能。通过与安全工具的集成,Harbor 能够在上传和管理镜像时对其进行漏洞检测。

1.3 实现离线漏洞扫描的技术方案

为了实现离线的漏洞扫描,需要通过Trivy代理将 最新漏洞数据库提前下载并复制到离线环境中。然后,结合 Harbor 的内置扫描器功能,通过配置 Harbor 使用 Trivy 作为扫描引擎,执行镜像的漏洞扫描。

  • Trivy 的离线数据库支持:可以预先在有网络的环境中下载漏洞数据库,并将其导入到离线环境中。
  • Harbor 的 Trivy 扫描集成: Trivy 作为harbor默认支持的扫描工具,与 Harbor 集成实现自动漏洞扫描。


2 实践:Trivy 为Harbor提供离线漏洞扫描

接下来,我们将详细介绍如何在离线环境中配置 Trivy 并结合 Harbor 实现镜像的漏洞扫描。

2.1 环境准备

  • Harbor:已经部署并运行在一个没有互联网访问的环境中。
  • Trivy:将在离线环境中使用,作为 Harbor 的漏洞扫描器。

2.2 安装Trivy作为数据库离线包下载代理

首先,你需要安装Trivy,可以根据你的操作系统使用以下方式安装。

2.2.1 通过包管理工具安装

通过包管理工具安装,执行以下命令安装:

sudo apt-get install wget apt-transport-https gnupg
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /usr/share/keyrings/trivy.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb generic main" | sudo tee -a /etc/apt/sources.list.d/trivy.list
sudo apt-get update
sudo apt-get install trivy

2.2.2 通过二进制方式安装

❔ 参考: trivy二进制包下载地址

下载二进制安装包

mkdir trivy
cd trivy
wget https://github.com/aquasecurity/trivy/releases/download/v0.55.1/trivy_0.55.1_Linux-64bit.tar.gz

解压安装包

TEMP_DIR=$(mktemp -d)   
tar xvf trivy_0.55.1_Linux-64bit.tar.gz -C ${TEMP_DIR}
sudo cp ${TEMP_DIR}/trivy /usr/local/bin/   

2.2.3 使用官方脚本安装

可以自动识别操作系统并完成包安装, 但是对网络有一定依赖。

curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sudo sh -s -- -b /usr/local/bin

2.2.4 查看trivy版本

你可以通过以下命令确认Trivy安装成功:

root@ub22:~/trivy# trivy version
Version: 0.55.1

2.3 下载最新的漏洞数据库:

下载离线漏洞库文件

trivy image --download-db-only --db-repository ghcr.io/aquasecurity/trivy-db:2

下载离线java缺陷库文件

trivy image --download-java-db-only --java-db-repository ghcr.nju.edu.cn/aquasecurity/trivy-java-db:1

参数说明:

查看文件结构

.cache/
├── motd.legal-displayed
└── trivy
    ├── db                # 缺陷数据库
    │   ├── metadata.json
    │   └── trivy.db
    └── java-db           # java缺陷数据库
        ├── metadata.json
        └── trivy-java.db

3 directories, 5 files

❔ 说明: 数据库文件会保存在当前用户主目录的~/.cache/ trivy 文件夹下。

2.4 使用oras下载数据库离线包(可选)

2.4.1 什么是oras

ORAS 是一个专门用于将各种类型的非容器镜像的二进制文件(如软件包、配置文件、Helm Charts、OCI Artifacts 等)推送和拉取到 OCI (Open Container Initiative) 兼容的镜像仓库中的轻量级的工具。

简单来说,ORAS 使得用户能够使用 OCI 兼容的仓库来存储和分发各种文件,而不仅仅是容器镜像。它扩展了 OCI 标准的适用范围,使得开发者可以将应用程序的所有部分(不仅是容器镜像)存储在同一个基础设施中。

2.4.2 安装oras

执行以下命令安装oars

VERSION="1.2.0"
curl -LO "https://github.com/oras-project/oras/releases/download/v${VERSION}/oras_${VERSION}_linux_amd64.tar.gz"
mkdir -p oras-install/
tar -zxf oras_${VERSION}_*.tar.gz -C oras-install/
sudo mv oras-install/oras /usr/local/bin/
rm -rf oras_${VERSION}_*.tar.gz oras-install/

检查oras版本信息,执行oras version:

Version:        1.2.0
Go version:     go1.22.3
Git commit:     dcef719e208a9b226b15bc6512ad729a7dd93270
Git tree state: clean

2.4.3 下载离线数据库文件

切换到临时目录

cd /tmp

下载离线漏洞库文件

oras pull ghcr.nju.edu.cn/aquasecurity/trivy-db:2 -v --insecure

下载离线java索引库文件

oras pull ghcr.nju.edu.cn/aquasecurity/trivy-java-db:1  -v --insecure

解压trivy-db并拷贝到cache目录

mkdir /tmp/trivy && tar -zxvf /tmp/db.tar.gz -C /tmp/trivy
cp -rfp /tmp/trivy/* /root/.cache/trivy/db/

解压trivy-java-db并拷贝到cache目录

mkdir /tmp/trivy-java  && tar -zxvf /tmp/javadb.tar.gz -C /tmp/trivy-java
cp -rfp /tmp/trivy-java/* /root/.cache/trivy/java-db

2.5 配置 Harbor 使用 Trivy 扫描器

在离线环境中,Harbor 默认集成了 Trivy 扫描器,但是需要配置 Trivy 以便它可以使用离线数据库。

在 Harbor 服务器中,编辑 harbor.yml 配置文件,确保启用了 Trivy 扫描器。

trivy:
  ignore_unfixed: false
  skip_update: true          # 关闭在线更新缺陷数据库
  skip_java_db_update: true  # 关闭在线更新java缺陷数据库
  offline_scan: true         # 启用离线扫描模式      
  security_check: vuln
  insecure: true

重启 Harbor 以应用配置更改:

./install.sh --with-trivy

或者

./prepare.sh
docker-compose restart


2.6 将数据库转移到离线环境

下载好的漏洞数据库文件需要定时上传至离线harbor环境中。通常实现方式有:

  • 如果代理服务器与其他离线环境内网未打通, 则手动传输。
  • 如果内网打通的场景,使用内网的文件传输工具(如scprsync)将相关文件传输到离线环境的服务器。

2.6.1 打包历史离线数据库文件

trivy数据目录说明:

  • 主路径: harbor会把主机的/data/trivy-adapter/trivy 映射到trivy-adapter容器的/home/scanner/.cache/trivy
  • db: 存放vulnerable缺陷数据库文件和元数据
  • fanal: Trivy 的核心库,可以作为 Go 库导入。您可以扫描 Go 中的配置文件并使用 Go 的测试方法(例如表驱动测试)测试您的自定义策略。这允许您使用实际的配置文件作为输入,从而轻松准备测试数据并确保您的自定义策略在实践中发挥作用。
  • java-db: 存放java缺陷数据库文件和元数据
  • backup: 自定义,存放备份数据库文件

创建备份文件夹

mkdir -p 
/data/trivy-adapter/trivy/backup

备份数据库

# 定义打包日期格式
CURRENT_DATE=$(date +'%Y%m%d')
BACKUP_PATH="/data/trivy-adapter/trivy/backup"

# 打包主数据库
tar -czf ${BACKUP_PATH}/db_${CURRENT_DATE}.tar.gz -C /data/trivy-adapter/trivy/db .

# 打包 Java 数据库
tar -czf ${BACKUP_PATH}/java_db_${CURRENT_DATE}.tar.gz -C /data/trivy-adapter/trivy/java-db .


2.6.2 同步最新的离线数据库文件

# 远程地址
REMOTE_IP="root@192.168.3.200"

# 定义本地数据库路径
LOCAL_DB_PATH="/data/trivy-adapter/trivy/db/"
LOCAL_JAVA_DB_PATH="/data/trivy-adapter/trivy/java-db/"

# 远程数据库缓存目录
REMOTE_DB_PATH="/root/.cache/trivy/db/"
REMOTE_JAVA_DB_PATH="/root/.cache/trivy/java-db/"

# 创建本地目录如果不存在
mkdir -p ${LOCAL_DB_PATH}
mkdir -p ${LOCAL_JAVA_DB_PATH}

# 同步 Trivy 主数据库
rsync -avz --delete ${REMOTE_IP}:${REMOTE_DB_PATH}/* ${LOCAL_DB_PATH}

# 同步 Trivy Java 数据库
rsync -avz --delete ${REMOTE_IP}:${REMOTE_JAVA_DB_PATH}/* ${LOCAL_JAVA_DB_PATH}

# 修改db文件的属主和属组
chown -R 10000.10000 ${LOCAL_DB_PATH} ${LOCAL_JAVA_DB_PATH}

2.7 扫描镜像并查看结果

2.7.1 查看trivy状态

配置完成后,登录Harbor的管理后台查看。

路径:首页→审查服务→扫描器

说明: trivy的配置已经生效。

2.7.2 找一个镜像手动扫描漏洞

路径:项目→选择hcie项目→选择redis镜像

点击镜像,并在操作选项中选择 “扫描”。-

扫描完成后,Harbor 的界面会显示每个镜像的漏洞情况,包括漏洞的严重等级(如 HighMediumLow)。

2.8 trivy下载和同步脚本

2.8.1 在trivy端和harbor端添加脚本

#!/bin/bash

# 任务1: Trivy更新离线数据库
update_trivy_db() {
    echo "开始更新 Trivy 数据库..."
    # 更新 Trivy 离线数据库
    trivy image --download-db-only --db-repository ghcr.io/aquasecurity/trivy-db:2
    trivy image --download-java-db-only --java-db-repository ghcr.nju.edu.cn/aquasecurity/trivy-java-db:1
    echo "Trivy 数据库更新完成。"
}

# 任务2: Harbor打包之前的数据库文件
backup_trivy_db() {
    echo "开始打包 Trivy 数据库文件..."

    # 定义打包日期格式
    CURRENT_DATE=$(date +'%Y%m%d')
    BACKUP_PATH="/data/trivy-adapter/trivy/backup"

    # 确保备份目录存在
    mkdir -p ${BACKUP_PATH}

    # 打包主数据库
    tar -zczf ${BACKUP_PATH}/db_${CURRENT_DATE}.tar.gz -C /data/trivy-adapter/trivy/db .

    # 打包 Java 数据库
    tar -zczf ${BACKUP_PATH}/java_db_${CURRENT_DATE}.tar.gz -C /data/trivy-adapter/trivy/java-db .

    echo "Trivy 数据库文件打包完成:db_${CURRENT_DATE}.tar.gz 和 java_db_${CURRENT_DATE}.tar.gz"

    # 任务3: 只保留最近7天的数据库文件
    echo "清理旧的备份文件..."
    find ${BACKUP_PATH} -type f -name "*.tar.gz" -mtime +7 -exec rm -f {} \;
    echo "旧的备份文件清理完成。"
}

# 任务4: 使用 rsync 同步最新数据库到本地目录
sync_trivy_db() {
    echo "开始同步数据库到本机..."
    # 定义远端地址
    REMOTE_IP="root@192.168.3.200"
    
    # 定义本地数据库路径
    LOCAL_DB_PATH="/data/trivy-adapter/trivy/db/"
    LOCAL_JAVA_DB_PATH="/data/trivy-adapter/trivy/java-db/"
    
    # 远端数据库缓存目录
    REMOTE_DB_PATH="/root/.cache/trivy/db/"
    REMOTE_JAVA_DB_PATH="/root/.cache/trivy/java-db/"
    
    # 创建本地目录如果不存在
    mkdir -p ${LOCAL_DB_PATH}
    mkdir -p ${LOCAL_JAVA_DB_PATH}
    
    # 同步 Trivy 主数据库
    rsync -avz --delete ${REMOTE_IP}:${REMOTE_DB_PATH} ${LOCAL_DB_PATH}
    
    # 同步 Trivy Java 数据库
    rsync -avz --delete ${REMOTE_IP}:${REMOTE_JAVA_DB_PATH} ${LOCAL_JAVA_DB_PATH}
    
    # 修改本地数据库属组和属主
    chown -R 10000.10000 ${LOCAL_DB_PATH} ${LOCAL_JAVA_DB_PATH}
    
    echo "数据库同步完成。"
}

# 检查第一个脚本参数并执行相应的函数
case "$1" in
    update_trivy_db)
        update_trivy_db
        ;;
    backup_trivy_db)
        backup_trivy_db
        ;;
    sync_trivy_db)
        sync_trivy_db
        ;;
    *)
        echo "Usage: $0 {update_trivy_db|backup_trivy_db|sync_trivy_db}"
        exit 1
        ;;
esac

给脚本添加执行权限

chmod +x /usr/local/bin/trivy_rsync.sh

2.8.2 设置定时任务

在trivy端添加更新数据库任务,在终端中运行以下命令编辑 crontab 文件:

crontab -e

添加以下定时任务调度规则:

# 每天0点更新Trivy数据库
0 0 * * * /usr/local/bin/trivy_rsync.sh update_trivy_db > /var/log/trivy.log 2>&1

在harbor端添加备份文件和同步文件的任务,在终端中运行以下命令编辑 crontab 文件:

crontab -e

添加以下定时任务调度规则:

# 每天23点30分打包数据库文件,清理旧文件
30 23 * * * /usr/local/bin/trivy_rsync.sh backup_trivy_db > /var/log/trivy.log 2>&1

# 每天0点30分同步数据库文件到本地
30 0 * * * /usr/local/bin/trivy_rsync.sh sync_trivy_db > /var/log/trivy.log 2>&1

3 总结

通过本文的介绍和实践步骤,我们展示了如何使用 Trivy 结合 Harbor 实现 离线漏洞扫描,在没有互联网访问的环境中仍然保持对容器镜像的安全检查。这个解决方案在隔离环境中,能够有效防止因未修补的漏洞导致的潜在攻击。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐