一、简言

Harbor 集成 Trivy,可自动对推送的容器镜像进行漏洞扫描。Trivy 作为轻量级安全扫描器,支持操作系统包(如 Alpine、CentOS)和应用依赖(如 Java、Python、Node.js)的漏洞检测。通过配置离线数据库,可在无外网环境下完成扫描,保障镜像安全合规。为了验证自己上传的镜像文件是否存在漏洞,所以要把Harbor中的Trivy用起来。

二、Harbor部署

#harbor安装包有两种,一种线上下载,一种线下,这边用的是线下下载安装
#下载地址:https://github.com/goharbor/harbor/releases
#https://github.com/goharbor/harbor/releases/download/v2.14.1/harbor-offline-installer-v2.14.1.tgz
cd /data/
tar -zxvf harbor-offline-installer-v2.14.1.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
#harbor.yaml配置参考下面修改,这里用的是http,https需要再配置,关键修改skip_update、skip_java_db_update、offline_scan这三个参数,因为trivy调用db库和java-db库需要访问外网,一般都会访问超时,不如直接不更新,手动下载库,离线扫描靠谱
#grep '^[[:space:][:alpha:]]' harbor.yml|grep -v '#'
hostname: 172.16.5.20
harbor_admin_password: HZQz34Hfs6JfMdj
data_volume: /home
skip_update: true
skip_java_db_update: true
offline_scan: true
#启动harbor
./install.sh --with-trivy #首次启动用,如果要启动trivy就要加上--with-trivy参数
docker-compose up -d #往后启动用
#停止harbor
docker-compose down

三、下载db库和java-db库

#安装oras
#下载oras地址:https://github.com/oras-project/oras/releases
wget https://github.com/oras-project/oras/releases/download/v1.3.0/oras_1.3.0_linux_amd64.tar.gz
#如果wget下载不下来就手动下载oras_1.3.0_linux_amd64.tar.gz
#解压
tar xvf oras_1.3.0_linux_amd64.tar.gz
#配置环境变量
mv oras /usr/local/bin/
#下载db库和java-db库
oras pull ghcr.io/aquasecurity/trivy-db:2
oras pull ghcr.io/aquasecurity/trivy-java-db:1

四、配置db库和java-db库

#因为我的挂载数据目录是/home(从harbor.yml的data_volume: /home得知),所以会有/home/trivy-adapter/trivy目录,我需要在这个目录下面创建两个目录db和java-db,将下载的db.tar.gz、javadb.tar.gz分别放在各自目录下解压
trivy
├── db
│   ├── metadata.json
│   └── trivy.db
└── java-db
    ├── metadata.json
    └── trivy-java.db
#创建存放库的目录
mkdir -pv /home/trivy-adapter/trivy/db
mkdir -pv /home/trivy-adapter/trivy/java-db
#解压下载的db库和java-db库到对应的目录下
tar xvf db.tar.gz -C /home/trivy-adapter/trivy/db
tar xvf javadb.tar.gz -C /home/trivy-adapter/trivy/java-d
#放好文件后注意权限问题
chown -R 10000.10000 /home/trivy-adapter
#重启harbor生效
cd /data/harbor #harbor有docker-compose.yml文件的目录
docker-compose down
docker-compose up -d

五、扫描不成功问题总结

#一、两个db库的没有设置或设置方式不对会出现问题,可以按上面方式进行操作
#二、报错:FATAL ... --skip-db-update cannot be specified on the first run

#三、可能打包镜像的dockerfile会有问题,解决方式先,上传个busybox试试,如果能正常扫描就说明打包的镜像可能有问题,可能是太大可能是版本太老等问题具体问题具体分析,我遇到的就是这个问题,下面是修改后的dockerfile文件。
cat Dockerfile
FROM eclipse-temurin:8-jre-jammy

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        fontconfig \
        libfreetype6 \
        fonts-noto-cjk \
    && rm -rf /var/lib/apt/lists/* \
    && fc-cache -f -v

WORKDIR /data/jar/banana
RUN mkdir -p log

COPY banana.jar .

VOLUME ["/data/jar/banana/log"]

EXPOSE 8080
CMD ["java","-jar","banana.jar"]
#CMD ["sh", "-c", "mkdir -p log && exec java -jar banana.jar >> log/app.log 2>&1"]
cat Dockerfile 
#FROM openjdk:8u212-jre-slim
FROM eclipse-temurin:8-jre-jammy

WORKDIR /data/jar/orange

COPY ./orange.jar ./

EXPOSE 8083

CMD ["sh", "-c", "java -server -Xms128m -Xmx128m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -jar orange.jar --spring.profiles.active=prod >> nohup.out 2>&1"]

六、定时更新db库和java-db库脚本

#vim /root/script/update-trivy-db.sh
#!/bin/bash
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
set -euo pipefail

# ======================
# 配置区
# ======================
TRIVY_ROOT_DIR="/home/trivy-adapter/trivy"   # Trivy 数据根目录
DB_DIR="$TRIVY_ROOT_DIR/db"
JAVA_DB_DIR="$TRIVY_ROOT_DIR/java-db"
LOG_FILE="/var/log/trivy-db-update.log"
ORAS_CMD="oras"

TRIVY_DB_REF="ghcr.io/aquasecurity/trivy-db:2"
TRIVY_JAVA_DB_REF="ghcr.io/aquasecurity/trivy-java-db:1"

# 日志函数
log() {
    echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}

# 检查依赖
check_deps() {
    for cmd in oras tar; do
        if ! command -v "$cmd" &> /dev/null; then
            log "ERROR: Required command '$cmd' not found. Exiting."
            exit 1
        fi
    done
}

main() {
    log "=== Starting Trivy DB update ==="

    # 确保目标目录存在
    mkdir -p "$DB_DIR" "$JAVA_DB_DIR"

    # === 更新 trivy-db ===
    log "Pulling $TRIVY_DB_REF ..."
    tmp_db=$(mktemp -d)
    if "$ORAS_CMD" pull "$TRIVY_DB_REF" --output "$tmp_db"; then
        log "Extracting trivy-db to $DB_DIR ..."
        tar -zxf "$tmp_db/db.tar.gz" -C "$DB_DIR" --strip-components=1
    else
        log "ERROR: Failed to pull trivy-db"
        rm -rf "$tmp_db"
        exit 1
    fi
    rm -rf "$tmp_db"

    # === 更新 trivy-java-db ===
    log "Pulling $TRIVY_JAVA_DB_REF ..."
    tmp_java=$(mktemp -d)
    if "$ORAS_CMD" pull "$TRIVY_JAVA_DB_REF" --output "$tmp_java"; then
        log "Extracting trivy-java-db to $JAVA_DB_DIR ..."
        tar -zxf "$tmp_java/javadb.tar.gz" -C "$JAVA_DB_DIR" --strip-components=1
    else
        log "ERROR: Failed to pull trivy-java-db"
        rm -rf "$tmp_java"
        exit 1
    fi
    rm -rf "$tmp_java"

    # 修复权限(Harbor trivy-adapter 用户 UID/GID = 10000)
    log "Fixing ownership to 10000:10000 ..."
    chown -R 10000:10000 "/home/trivy-adapter"

    # 清理可能残留的 .tar.gz(虽然不太可能留在这)
    find "$DB_DIR" "$JAVA_DB_DIR" -name "*.tar.gz" -delete

    log "=== Trivy DB update completed successfully ==="
}

check_deps
main
#设置定时任务(每周日凌晨 2 点更新)
crontab -e
0 2 * * 0 /root/script/update-trivy-db.sh >/dev/null 2>&1
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐