diff --git a/scripts/pipeline/scan-sbom.sh b/scripts/pipeline/scan-sbom.sh index deaa8d3..7816f4b 100755 --- a/scripts/pipeline/scan-sbom.sh +++ b/scripts/pipeline/scan-sbom.sh @@ -8,8 +8,8 @@ # 취약점 DB 만 있으면 되며, CVE DB 갱신 시 재pull 없이 재스캔할 수 있다. # # 사용: -# bash doc/scripts/generate-sbom.sh images_final.tsv . # 선행: sbom/ 생성 -# bash doc/scripts/scan-sbom.sh . # SBOM 취약점 스캔 +# bash scripts/pipeline/generate-sbom.sh images_final.tsv . # 선행: sbom/ 생성 +# bash scripts/pipeline/scan-sbom.sh . # SBOM 취약점 스캔 # # 인자: # $1 SBOM 작업 디렉토리 (sbom/ 과 sbom-index.tsv 가 있는 곳. 기본: 현재 디렉토리) @@ -124,16 +124,37 @@ trivy image --download-db-only >>"$LOG" 2>&1 \ echo ">> [$(ts)] 스캔 시작 (parallel=$PARALLEL)" | tee -a "$LOG" >&2 P1=$(date +%s) -# 각 타깃 라인(image⇥sbom_file)을 워커로. -I{} 는 라인 단위로 아이템을 읽으므로 -# {} 에 탭 포함 전체 라인이 들어온다. bash -c 안에서 cut 으로 탭 분해(BSD/GNU 공통). -xargs -P "$PARALLEL" -I{} bash -c ' - im=$(printf %s "$1" | cut -f1) - sf=$(printf %s "$1" | cut -f2) - [ -n "$im" ] && bash "$0" --scan-one "$im" "$sf" "$2" "$3" -' "$SELF" {} "$REPORTS" "$LOG" < "$TARGETS" \ - >> "$RESULTS" +# xargs 를 쓰지 않는다. macOS(BSD)에서 두 가지가 깨진다 — 둘 다 실측으로 확인했다 +# (동일 파이프라인의 security-catalog 프로젝트에서 먼저 발견됨). +# +# 1. `xargs -I{}` 가 치환 시 **탭을 공백으로 바꾼다.** 그러면 `cut -f`(탭 구분)가 +# 구분자를 못 찾고 BSD cut 은 라인 전체를 반환하므로 이미지명과 SBOM 경로가 +# 한 덩어리가 되어 `failed to open sbom file` 로 실패한다. +# 2. `xargs -I` 는 조립 인자를 짧게 제한한다. SBOM 경로가 길면 대상이 조용히 +# 누락되고도 스크립트가 성공으로 보고할 수 있다. +# +# `read` 로 탭을 직접 분해하고 배치 단위로 wait 한다. `wait -n` 은 bash 4.3+ 이므로 +# macOS 기본 bash 3.2 에서 쓸 수 없어 batch-wait 방식을 쓴다. +n=0 +while IFS="$(printf '\t')" read -r im sf; do + [ -n "$im" ] && [ -n "$sf" ] || continue + bash "$SELF" --scan-one "$im" "$sf" "$REPORTS" "$LOG" >> "$RESULTS" & + n=$((n+1)) + [ $(( n % PARALLEL )) -eq 0 ] && wait +done < "$TARGETS" +wait echo ">> [$(ts)] 스캔 완료 ($(fmt_elapsed $(( $(date +%s) - P1 ))))" | tee -a "$LOG" >&2 +# 누락 검출 — 대상 수와 결과 수가 다르면 실패시킨다. "스캔되지 않음" 이 "취약점 +# 없음" 으로 오인되는 것이 이 파이프라인의 최악 실패다. +GOT="$(grep -c . "$RESULTS" 2>/dev/null || echo 0)" +if [ "$GOT" -ne "$N" ]; then + echo "!! 스캔 대상 $N 개 중 $GOT 개만 결과가 있다 — 누락 발생" | tee -a "$LOG" >&2 + awk -F'\t' 'NR==FNR{seen[$1]=1;next} !($1 in seen){print "!! 누락: "$1}' \ + "$RESULTS" "$TARGETS" | tee -a "$LOG" >&2 + exit 1 +fi + TOTAL=$(( $(date +%s) - RUN_START )) # 취약점 스캔 단계(오프라인) 소요 GEN_SECS=$(cat "$OUT_DIR/.sbom-gen-seconds" 2>/dev/null || echo "") # SBOM 생성 단계(이미지 pull) 소요 python3 - "$RESULTS" "$CHARTMAP" "$SEVERITY" "$TOTAL" "$(ts)" "$SUMMARY_TSV" "${GEN_SECS:-}" <<'PY' | tee "$SUMMARY_MD" >&2