Files
service-catalog/doc/scripts/extract-helm-images.sh
T
wbsong111 2af7fcb43d feat(sbom): add Helm catalog SBOM+vuln pipeline (CycloneDX)
manifests/helm 카탈로그 전 이미지의 SBOM(CycloneDX)과 취약점 리포트를
생성하는 파이프라인 추가. 컨테이너 내부 trivy/helm 바이너리 직접 호출.

- doc/scripts/extract-helm-images.sh: helm template 렌더로 이미지 인벤토리 추출
- doc/scripts/generate-sbom.sh: trivy image --format cyclonedx (이미지 1회 pull)
- doc/scripts/scan-sbom.sh: trivy sbom 로 SBOM 기반 오프라인 취약점 스캔
- .github/workflows/sbom.yml: 스케줄(전체)+PR(증분)+수동, 산출물은 아티팩트
- doc/sbom-pipeline.md: 파이프라인 설계·운영 문서(단일)
- latest/무태그 digest 고정: mlflow postgresql, vllm-openai(v0.24.0)
- .gitignore: 파이프라인 산출물 제외

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 12:15:58 +09:00

87 lines
3.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# extract-helm-images.sh
# dip-catalog 정적 Helm 카탈로그에서 컨테이너 이미지 인벤토리를 추출한다.
#
# 방법 (100% deterministic, LLM 미사용):
# 각 차트 버전 디렉토리를 `helm template` 로 렌더 → 렌더된 매니페스트에서
# `image:` 필드를 추출 → 정규화/중복 제거.
#
# custom-values.yaml 이 있으면 적용하여 "실제 배포되는(effective) 이미지"를
# 뽑는다. 없으면 차트 기본값으로 렌더한다.
#
# 사용:
# bash doc/scripts/extract-helm-images.sh [HELM_ROOT] [OUT_DIR]
# HELM_ROOT 기본값: <repo>/manifests/helm
# OUT_DIR 기본값: 현재 디렉토리
#
# 산출물:
# images_final.tsv chart<TAB>version<TAB>image (정렬/중복제거)
# render_status.tsv chart<TAB>version<TAB>mode<TAB>status
#
# 요구사항: helm v3, bash, awk, sed, grep
# =============================================================================
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
HELM_ROOT="${1:-$(cd "$SCRIPT_DIR/../../manifests/helm" && pwd)}"
OUT_DIR="${2:-$(pwd)}"
# bitnamilegacy 이미지가 있는 차트는 Bitnami common 의 insecureImages 가드에
# 걸리므로 렌더 시 허용 플래그가 필요하다.
KUBE_VERSION="${KUBE_VERSION:-1.31.0}"
COMMON_SET=(--set global.security.allowInsecureImages=true)
RAW="$OUT_DIR/images_raw.tsv"
FINAL="$OUT_DIR/images_final.tsv"
STATUS="$OUT_DIR/render_status.tsv"
: > "$RAW"; : > "$STATUS"
cd "$HELM_ROOT"
extract_images() { # stdin: 렌더된 yaml → stdout: 이미지 문자열
grep -ioE '^[[:space:]]*(- )?image:[[:space:]]*"?[^"[:space:]]+' \
| sed -E 's/.*image:[[:space:]]*"?//' \
| grep -vE '^$'
}
for chart in */; do
chart="${chart%/}"
for vdir in "$chart"/*/; do
[ -f "${vdir}Chart.yaml" ] || continue
version="$(basename "$vdir")"
args=(template t "$vdir" --kube-version "$KUBE_VERSION" "${COMMON_SET[@]}")
mode="default"
if [ -f "${vdir}custom-values.yaml" ]; then
args+=(-f "${vdir}custom-values.yaml")
mode="effective"
fi
if out="$(helm "${args[@]}" 2>/tmp/_helmerr)"; then
echo -e "${chart}\t${version}\t${mode}\tOK" >> "$STATUS"
elif [ "$mode" = "effective" ] && out="$(helm template t "$vdir" --kube-version "$KUBE_VERSION" "${COMMON_SET[@]}" 2>/tmp/_helmerr)"; then
echo -e "${chart}\t${version}\tdefault-fallback\tOK" >> "$STATUS"
else
echo -e "${chart}\t${version}\t${mode}\tFAIL: $(head -1 /tmp/_helmerr | cut -c1-120)" >> "$STATUS"
out=""
fi
[ -n "$out" ] || continue
while read -r img; do
[ -z "$img" ] && continue
echo -e "${chart}\t${version}\t${img}" >> "$RAW"
done < <(printf '%s\n' "$out" | extract_images)
done
done
# 정규화(따옴표 제거) + 정렬 + 중복 제거
awk -F'\t' '{gsub(/^['"'"'"]+|['"'"'"]+$/,"",$3); if($3!="") print $1"\t"$2"\t"$3}' "$RAW" \
| sort -u > "$FINAL"
echo "== 렌더 상태 =="
awk -F'\t' '{s=$4; sub(/FAIL.*/,"FAIL",s); print s}' "$STATUS" | sort | uniq -c
echo "== 커버 차트 : $(cut -f1 "$FINAL" | sort -u | wc -l | tr -d ' ') =="
echo "== 고유 이미지: $(cut -f3 "$FINAL" | sort -u | wc -l | tr -d ' ') =="
echo "== 산출물 : $FINAL =="