Files
service-catalog/doc/decisions/0005-self-build-drift-check-removed.md
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

76 lines
4.7 KiB
Markdown

# 0005. 자체 빌드 드리프트 스캔·재빌드 트리거를 dip-catalog에서 제거한다
- 날짜: 2026-08-26
- 상태: 확정
## 결정
dip-catalog에서 자체 빌드 이미지 재빌드 트리거와 전용 드리프트 스캔을 모두 제거한다 —
`.github/workflows/self-build-drift-check.yml``scripts/build/check-rebuild-needed.py`
삭제한다. 자체 빌드 이미지의 CVE는 `sbom.yml`이 다른 카탈로그 이미지와 동일하게
스캔·보고하고, 재빌드 여부·시점은 전적으로 `hardened-containers``rescan.yml`
자율 결정한다.
## 배경
`self-build-drift-check.yml`은 두 가지를 했다: (1) 배포 중인 자체 빌드 이미지를 스캔해
재빌드 대상을 판정하고, (2) 대상이 있으면 별도 레포 `hardened-containers`
`build-image.yml``workflow_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.sh`
`custom-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.py``sbom.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.sh``custom-values.yaml`만 적용해 렌더하므로 `dip-values.yaml`에만
있는 태그는 스캔되지 않는다. 현재 카탈로그에서는 두 파일의 paasup 태그가 일치해 실질
영향이 없음을 확인했다(cnpg-cluster 1.0.0/1.1.0). `manifests/applicationset/**` 미스캔
(MEMORY.md #42)과 같은 성격의 공백이다.
## 재검토 조건
- `hardened-containers``rescan.yml`이 장기간 중단되거나 신뢰할 수 없게 되면 — 그 경우
dip-catalog 쪽에 독립적인 드리프트 감시가 다시 필요해진다.
- `dip-values.yaml`에만 존재하는 자체 빌드 태그가 실제로 생기면 — 이 결정의 전제("두
values 파일의 paasup 태그가 일치한다")가 깨지므로 스캔 커버리지를 다시 검토해야 한다.