Files
service-catalog/doc/decisions/0005-self-build-drift-check-removed.md
T
wbsong111 f5b8e4b91f 자체 빌드 드리프트 스캔·재빌드 트리거를 제거하고 CI 파이프라인을 정리한다
hardened-containers가 이미 rescan.yml로 매일 자율 재스캔·재빌드하고, sbom.yml이
custom-values.yaml 기준으로 자체 빌드 이미지를 다른 카탈로그 이미지와 동일하게
스캔하고 있어 self-build-drift-check.yml의 트리거·전용 스캔이 순수 중복이었다
(SECURITY_IMAGES_DISPATCH_TOKEN도 등록된 적 없어 트리거 스텝은 항상 실패하던
죽은 코드). check-rebuild-needed.py가 더하던 fixable/no-fix 구분도 cve-gate.py
리포트에 이미 있어 흡수할 필요 없이 삭제했다. 근거는 ADR 0005.

곁들여 CI 위생 문제(trivy DB 캐시 없음, concurrency 없음, catalog-tag-update.yml의
브랜치 누적)를 함께 고치고, hardened-containers의 docs/image-authoring.md가
docs/image-authoring/ 로 분할된 것을 반영해 관련 링크를 정정했다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 09:48:48 +09:00

4.7 KiB

0005. 자체 빌드 드리프트 스캔·재빌드 트리거를 dip-catalog에서 제거한다

  • 날짜: 2026-08-26
  • 상태: 확정

결정

dip-catalog에서 자체 빌드 이미지 재빌드 트리거와 전용 드리프트 스캔을 모두 제거한다 — .github/workflows/self-build-drift-check.ymlscripts/build/check-rebuild-needed.py를 삭제한다. 자체 빌드 이미지의 CVE는 sbom.yml이 다른 카탈로그 이미지와 동일하게 스캔·보고하고, 재빌드 여부·시점은 전적으로 hardened-containersrescan.yml이 자율 결정한다.

배경

self-build-drift-check.yml은 두 가지를 했다: (1) 배포 중인 자체 빌드 이미지를 스캔해 재빌드 대상을 판정하고, (2) 대상이 있으면 별도 레포 hardened-containersbuild-image.ymlworkflow_dispatch로 트리거했다.

근거

자체 빌드 이미지의 CVE는 이미 세 겹으로 덮여 있었다.

  1. 빌드 시점hardened-containers가 강제 zero-CVE 게이트를 통과한 이미지만 push하고, published.json은 게이트 PASS + 실제 push된 것만 기록한다. 새로 발행된 이미지는 구조적으로 깨끗하다.
  2. 빌드 이후 드리프트 — 그 레포의 rescan.yml이 매일 재스캔하고 자율적으로 재빌드한다. dip-catalog가 별도로 트리거를 보내는 건 이 루프를 중복시킬 뿐이다. 실제로도 SECURITY_IMAGES_DISPATCH_TOKEN 시크릿이 한 번도 등록된 적 없어 트리거 스텝은 실행할 때마다 실패하는 죽은 코드였다.
  3. dip-catalog가 실제 배포 중인 것sbom.yml이 이미 스캔한다. extract-helm-images.shcustom-values.yaml을 적용해 helm template로 렌더하므로 docker.io/paasup/*가 그대로 스캔 대상에 들어가고, cve-gate.py가 같은 게이트 규칙(실효 등급 max(벤더,NVD) · 승인 예외)으로 판정한다. 같은 이미지를 주 2회(일 18:00 · 월 02:00) 따로 스캔하고 있었을 뿐이다.

check-rebuild-needed.py가 유일하게 더하던 "수정 버전이 있는가(fixable/no-fix)" 분류조차 새 정보가 아니었다 — cve-gate.py의 리포트 테이블에 이미 "수정 버전" 컬럼이 있고 FixedVersion으로 채워진다. 이 스크립트는 같은 findings를 자체 빌드 8개 기준으로 다시 묶어 보여줄 뿐이었다.

탈락한 후보

  • (a) 현행 유지 — 트리거 + 별도 워크플로 그대로. 위 근거대로 순수 중복이라 기각.
  • (b) 트리거만 제거, 워크플로는 스캔·보고용으로 존치sbom.yml과 같은 이미지를 또 스캔하는 문제(주 2회 중복)가 남아 기각.
  • (c) check-rebuild-needed.pysbom.yml의 리포트 스텝으로 흡수 — SBOM/리포트 파일 명명 규칙이 두 파이프라인에서 동일해(tr '/:@' '___' vs re.sub(r"[/:@]","_",ref)) 기술적으로는 가능했다. 하지만 cve-gate.py 리포트에 이미 "수정 버전" 컬럼이 있어 흡수해도 새 정보가 생기지 않음을 확인해 기각했다 — 같은 findings의 재그룹핑을 위해 스크립트와 워크플로 스텝을 유지할 이유가 없었다.

받아들인 비용

  • 자체 빌드 8개만 좁혀 보는 전용 표가 사라진다 — sbom.yml 리포트에서 docker.io/paasup/*를 골라 봐야 한다.
  • 자체 빌드 이미지 리포트 주기가 월요일 02:00 → 일요일 18:00(sbom.yml 스케줄)로 바뀌고, 그 워크플로가 실패하면 자체 빌드 리포트도 함께 보이지 않는다.
  • dip-catalog가 옛 태그에 멈춰 있어도 스스로 재빌드를 재촉할 수단이 없다 — Job Summary 리포트를 사람이 보고 수동으로 판단해야 한다. 단, catalog-tag-update.yml이 매일 폴링해 보통 하루 안에 따라잡으므로 드문 시나리오다.

알려진 잠재 공백 (이번 결정이 만든 것이 아니라 기존부터 있던 것 — 기록만)

extract-helm-images.shcustom-values.yaml만 적용해 렌더하므로 dip-values.yaml에만 있는 태그는 스캔되지 않는다. 현재 카탈로그에서는 두 파일의 paasup 태그가 일치해 실질 영향이 없음을 확인했다(cnpg-cluster 1.0.0/1.1.0). manifests/applicationset/** 미스캔 (MEMORY.md #42)과 같은 성격의 공백이다.

재검토 조건

  • hardened-containersrescan.yml이 장기간 중단되거나 신뢰할 수 없게 되면 — 그 경우 dip-catalog 쪽에 독립적인 드리프트 감시가 다시 필요해진다.
  • dip-values.yaml에만 존재하는 자체 빌드 태그가 실제로 생기면 — 이 결정의 전제("두 values 파일의 paasup 태그가 일치한다")가 깨지므로 스캔 커버리지를 다시 검토해야 한다.