Commit Graph

11 Commits

Author SHA1 Message Date
wbsong111 7746570ec0 자체 빌드 이미지 프레임워크를 security-images 레포로 이관하고 카탈로그 쪽을 정리한다
images/·scripts/build/build-hardened-image.sh·suggest-go-upgrades.py·
build-image.yml·.claude/image-authoring.md·이미지 ADR(0001·0002·0004)을 삭제했다 —
전부 별도 public 레포 security-images 로 이미 이관됐다.

카탈로그 쪽에는 "무엇을 배포 중인가"를 아는 부분만 남긴다:
- catalog/image-map/<image>.env — 옛 catalog.env 의 카탈로그 레이아웃 정보만 뗀 것
- scripts/build/check-rebuild-needed.py — 드리프트 탐지(A 파트)만 남기고 핀 판단
  (B 파트: pin_changes/apply_changes/parse_module_specs)은 제거
- scripts/build/apply-published-tags.py(신규) — security-images 의 published.json
  을 읽어 카탈로그 values 를 패치
- .github/workflows/{self-build-drift-check,catalog-tag-update}.yml(신규) — 각각
  드리프트 스캔+트리거, 발행 태그 반영

effective_severity 를 cve-gate.py 로 옮겼다 — check-rebuild-needed.py 가 핀 도구를
거치지 않고 게이트를 직접 로드하게 하기 위한 선행 작업이다.

두 레포의 계약은 published.json 스키마 하나뿐이다 — security-images 는 이 카탈로그를
모른다(단방향 의존). 이관 배경·결합점 전체는
doc/migrations/self-build-images-to-security-images.md.

부수 수정: 자체 빌드 이미지를 참조하는 차트 values/README 의 죽은 링크(images/**,
doc/decisions/000{1,2,4}, .claude/image-authoring.md)를 security-images 레포를
가리키는 서술로 교체. deploy-test 스크립트·CUSTOM-README 의 개인 Docker Hub 계정
(docker.io/wbsong111) 을 docker.io/paasup 로 교체.

pitfalls.md 의 "스캐너 결과를 그대로 믿지 말 것" 절은 sbom-cve-gate skill 이 차트
축 설명에 실제로 참조하고 있어 남겼다 — "이미지 태그의 베이스 OS" 절만 제거했다
(다른 참조 없음, security-images 문서로 이관 완료).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 15:21:29 +09:00
wbsong111 7d36f4fddb SBOM_PIPELINE_IMAGE 를 docker.io/paasup 으로 옮긴다 (#30)
파이프라인 실행 이미지가 개인 네임스페이스(docker.io/wbsong111)를 가리키고 있었다. 카탈로그의
다른 자체 빌드 이미지는 2026-08-03 에 전부 docker.io/paasup 으로 이전됐는데 이것만 남아 있었다 —
"카탈로그가 배포하는 이미지가 아니라 CI 도구" 라 이전 대상에서 빠졌던 것이다.

  before  docker.io/wbsong111/sbom-pipeline:latest
  after   docker.io/paasup/sbom-pipeline:20260820

롤링 태그를 쓰지 않는다
---------------------
:latest 를 유지하지 않고 날짜 태그로 갔다. 이 Dockerfile 은 helm/trivy 를 **빌드 시점 최신으로
설치**하므로 같은 파일이 매번 다른 이미지를 낸다 — 태그가 "무엇으로 스캔했는지" 의 기록이어야
한다. Repo Variable 이 전체 ref 를 담으므로 고정 태그를 써도 워크플로 수정이 필요 없다.

이번 이미지가 담은 것: helm v3.21.4 · trivy 0.74.0 · python 3.13.5 · git 2.47.3

검증
----
  push        docker.io/paasup/sbom-pipeline:20260820 (linux/amd64)
  변수 갱신    gh variable set SBOM_PIPELINE_IMAGE
  CI 실제 동작 helm-catalog-sbom limit=3 실행 → 전체 success
              (Preflight 도구 확인 · 인벤토리 추출 · SBOM · 스캔 · 게이트 판정 전부 통과)

문서의 낡은 참조 4곳(doc/sbom-pipeline.md)과 Dockerfile 헤더 절차, sbom.yml 주석 예시를 고쳤다.
Dockerfile 헤더에는 왜 :latest 를 쓰지 않는지도 적었다.

Closes #30

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 16:55:55 +09:00
wbsong111 bce6255468 applicationset 미스캔은 결함이 아니라 의도 — 이유와 함께 적는다
"manifests/applicationset/** 는 어떤 워크플로도 보지 않는다" 를 사각지대로 적었는데 잘못된
평가였다. 그 아래 dip-values.yaml 은 dip-console 이 배포 values 를 만들 때 쓰는 참조 파일이고,
같은 이미지를 manifests/helm/ 차트에서 이미 스캔·게이트한다. 같은 이미지를 두 번 스캔할 이유가
없어 인벤토리 추출 대상을 manifests/helm/ 으로 한정한 것이다.

이유를 적어두지 않으면 다음 사람이 또 "미검사 결함" 으로 보고한다 — 실제로 내가 그렇게 했다.

다만 그 가정이 무엇에 의존하는지도 함께 적었다: **두 곳이 같은 이미지를 가리킨다는 것**.
참조 파일이 차트와 다른 태그를 들고 있으면 스캔한 것과 배포되는 것이 갈린다. 태그 동기화는
스캔 커버리지와 별개 문제이고 patch-catalog-tag.py 의 CHART_DIRS 범위가 그것을 결정한다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 16:41:40 +09:00
wbsong111 79555215a0 파이프라인을 두 축으로 갈라 소유 문서를 확정한다
"파이프라인이 chart CVE 조치와 커스텀 이미지 빌드 2개로 나뉘어 있는가" 를 확인하다가 실제
구성이 그 모델과 다른 것이 드러났다.

  1. 워크플로는 3개다. cve-edge-post.yml 이 CLAUDE.md 에서 디렉토리 트리와 괄호 안에만
     등장해 파이프라인으로 읽히지 않았다 — "2개" 인식의 근원이다.
  2. doc/sbom-pipeline.md 가 두 축을 한 파일에 담고 있었다(자체 빌드 절 43줄).
     커스텀 이미지가 별도 레포로 분리될 예정인데 이 상태로는 분리 때 파일을 찢어야 한다.
  3. 그 문서가 이미 뒤집힌 결정을 담고 있었다 — "schedule 트리거는 없다. 블라인드 정기
     재빌드는 제거했다" 인데 PR #40 이 schedule 을 추가했다.

축을 이렇게 갈랐다
-----------------
  차트 카탈로그 축   sbom.yml · cve-edge-post.yml   →  doc/sbom-pipeline.md
  자체 빌드 축       build-image.yml                →  .claude/image-authoring.md

doc/sbom-pipeline.md — 차트 축만 남긴다
  - 상단에 "이 문서가 다루는 축" 을 두고 자체 빌드는 링크로 넘긴다
  - 자체 빌드 절(43줄)을 image-authoring.md 로 이관
  - sbom.yml ↔ cve-edge-post.yml 비교 표 신설. **판정기가 두 벌**이라는 사실을 명시했다 —
    cve-edge-post.yml 은 집계를 워크플로 YAML 안의 인라인 python 으로 갖고 있어 승인 예외도
    실효 등급도 적용하지 않는다. 같은 스캔 데이터에서 다른 숫자가 나올 수 있다
  - PR 을 실제로 막는 게이트는 images/** PR 뿐이고 manifests/applicationset/** 는 아무
    워크플로도 보지 않는다는 사각지대를 적었다

.claude/image-authoring.md — 자체 빌드 축의 단일 출처가 된다
  - 이관받은 워크플로 서술 + "이 워크플로의 게이트는 강제다"(차트 축 warn-only 와 다르다는
    사실이 지금까지 한 곳에만 있었다)
  - schedule 결정 정정 — 지금 것은 블라인드가 아니라 CVE 트리거다. 수정 버전이 있는 차단
    CVE 가 있을 때만 빌드하고 없으면 아무것도 하지 않는다. 거부된 것과 조건이 다르다
  - "레포 분리 후 무엇이 끊기는가" 결합점 7개 표. 3번(탐지가 카탈로그를 읽는다)이 가장 크고,
    게이트 공유는 workflow_call 이 아니라 composite action 이어야 한다는 것도 적었다
    (workflow_call 은 별도 job 이라 $OUT_DIR 를 공유하지 못한다)
  - 파일 상단에 "레포 분리 시 images/·scripts/build/·build-image.yml 과 함께 이동한다"
  - #35 에서 실측한 매핑 함정 추가 — CHART_DIRS 에 없는 파일은 patch-catalog-tag.py 가
    검사조차 하지 않아 cnpg-cluster/1.1.0 이 조용히 빠졌다

CLAUDE.md — 지도만 남긴다
  두 축 비교 표(질문·워크플로·게이트 강도·소유 문서)로 바꾸고 메커니즘 서술을 걷어냈다.
  cve-edge-post.yml 을 파이프라인으로 처음 등재했다.

검증
----
  표의 사실 대조   각 워크플로의 cve-gate 호출·warn-only·활성 schedule 을 파일에서 확인
  축 분리          sbom-pipeline.md 에 남은 build-image.yml 언급은 전부 링크·대조·시크릿
                   공유 문장(의도된 것)
  뒤집힌 결정      "schedule 트리거는 없다" 잔존 0건
  링크             3개 문서의 로컬 링크 전부 실재

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20 16:26:14 +09:00
wbsong111 4f67f63f69 SBOM 파이프라인 문서 정비 + 이미지 목록 열거 제거
## doc/sbom-pipeline.md — 중복·모순 정리 (328 → 286줄)

같은 사실이 여러 절에 흩어져 있었고, 일부는 문서가 아니라 변경 이력이었다.

- `SEVERITY` 를 전 심각도로 덮어써야 하는 이유가 환경변수 절·CI 절·요약 절 3곳에
  있었다. 스크립트 절의 blockquote 하나로 합쳤다 — "게이트를 돌릴 거라면 전 심각도로
  스캔해야 한다"가 핵심이고 나머지는 그 결과다.
- Job Summary 1MB 제한이 CI 절과 결과 확인 절에 중복됐다. CI 절 하나로 합쳤다.
- `--warn-only` 서술이 mermaid 라벨·CI 절·게이트 절·트리아지 절 4곳에 있었다.
  게이트 절 하나로 합치고, `build-image.yml` 쪽은 이미 강제라는 대비를 함께 적었다.
- 자체 빌드 트리거 표가 "PR 은 push 안 함"을 말하는데 바로 아래 불릿이 같은 말을
  반복했다. 표는 그대로 두고 불릿은 **왜** 그런지(REGISTRY 미전달 → localhost 태그라
  push 를 시도할 수조차 없다)만 남겼다.
- "오해를 주던 단일 '총 소요'는 제거" 같은 변경 이력 서술을 걷어냈다. 문서는 현재
  상태를 적는 곳이다.
- "첫 전체 실행 결과(2026-07-08)" 절은 수치를 싣고 바로 아래에서 "현재 수치가
  아니다"로 무효화하는 구조였다. 절 자체를 없애고, 거기서 유일하게 쓸모 있던 사실
  (SBOM 생성 실패는 대부분 사설/미인증 레지스트리이거나 대용량 timeout)만 스크립트
  절로 옮겼다.
- "실행 이력(2026-08-04)" 절은 MEMORY.md 와 중복이라 제거했다. 거기서만 알 수 있던
  사실(Actions 시크릿의 push 권한 확인)은 GitHub 설정 표에 반영했다.
- `CVE_API_KEY` 가 본문에만 있고 GitHub 설정 표에 빠져 있어 추가했다.
- 아키텍처 절 불릿이 mermaid 서브그래프 라벨과 같은 말을 하고 있어, "pull 을 ② 한
  곳에 몰아둔 것이 핵심"이라는 결론 한 문장으로 줄였다.

## 이미지 목록을 문서에 박아두지 않는다

이미지는 계속 추가되므로 열거하면 추가할 때마다 낡는다. `images/` 디렉토리를 단일
출처로 삼고 CLAUDE.md·image-authoring.md·build-image.yml·sbom-pipeline.md 의 열거를
걷어냈다. keycloak README 의 베이스 OS 결정 근거도 "기존 3종" 대신 "먼저 들어온
이미지들"로 바꿨다 — 근거의 내용은 그대로다.

## 현황 서술 정정

- build-image.yml 주석이 "아직 도입된 자체 빌드 이미지가 없다(images/ 가 비어 있음)"
  로 남아 있었다. 이 레포 CI 에서 빌드→검증→게이트→push→카탈로그 브랜치 push 까지
  실제로 검증된 상태다.
- MEMORY.md: cve-exceptions.json 첫 예외 등록, 베이스 OS 정책 확정, PR 자동 생성이
  조직 정책으로 불가하다는 실측(run 30882785612)을 반영했다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-07 14:27:03 +09:00
wbsong111 6597059a15 scan-sbom.sh: CoverageProbe 커버리지 자가진단 이식 + 관련 파이프라인 버그 수정
security-catalog 프로젝트에서 자체 빌드 이미지 3종을 실제로 로컬 빌드·게이트
검증하는 과정에서 발견한 문제들:

- extract-helm-images.sh 가 `image:` 필드만 잡고 `imageName:`(CNPG Cluster CRD 관례)
  은 놓쳐, cnpg-cluster 차트의 이미지가 SBOM·스캔·게이트 어디에도 안 나타났다.
- patch-catalog-tag.py 의 split 포맷 패처가 registry 필드가 따로 없고 repository 에
  registry+repo 를 합쳐 쓰는 차트(cloudnative-pg 오퍼레이터, 업스트림 템플릿이
  image.registry 를 아예 참조하지 않음)에서 tag 만 조용히 갱신하고 repository 는
  그대로 남겨 깨진 참조를 만들 수 있었다.
- CoverageProbe(센티널 패키지 주입 재스캔으로 "0건"과 "측정 안 됨"을 구분)가
  이식되지 않아, 전 심각도 0건인 자체 빌드 이미지가 실제로는 깨끗한데도 게이트가
  "데이터 커버리지 이상"으로 오탐 처리했다 — security-catalog 의 scan-sbom.sh 를
  이식해 해소. cve-gate.py 는 이미 이 키를 읽도록 구현돼 있어 소비 쪽 변경은 없다.

rpm(SUSE)·deb(Debian)·apk(Alpine) 세 센티널 경로와 병렬 스캔 회귀를 로컬에서
확인했고, 이식 후 cloudnative-pg·cnpg-postgresql 게이트가 실제로 FAIL→PASS 로
바뀌는 것도 확인했다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-03 15:30:57 +09:00
wbsong111 5e1422e0e4 CVE/SBOM 게이트 문서화: CLAUDE.md 3번째 서브시스템 + MEMORY.md 신설
CLAUDE.md 에 CVE/SBOM 게이트 서브시스템 절 추가(기존 7개 설계 원칙·구현
현황은 변경 없음). doc/sbom-pipeline.md 에 게이트 판정 절 + 커버리지
자가진단 미이식 제약 명시. MEMORY.md 신설 — warn-only 상태, 45+ 차트
미검증, 자체 빌드 프레임워크 미사용, SBOM_PIPELINE_IMAGE 재빌드 보류 등
후속 결정 사항 기록.
2026-08-03 10:06:48 +09:00
wbsong111 ac119a3559 fix(sbom-ci): auth docker.getcollate.io (Docker Hub proxy) + raise trivy timeout
openmetadata 실패의 진짜 원인은 참조 오류가 아니라 docker.getcollate.io(Docker Hub 프록시)의
익명 pull rate limit(TOOMANYREQUESTS)였음. 인증 config 에 getcollate 를 추가(Docker Hub
자격증명)하고, 대용량 이미지 분석을 위해 trivy 타임아웃 기본값을 10m→15m(TRIVY_TIMEOUT).
로컬 검증: 인증+타임아웃으로 openmetadata server SBOM 생성 성공(655 comp).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 16:55:08 +09:00
wbsong111 c36edb3015 sbom-ci: meaningful stage timings, dynamic severity cols, doc update
- scan-sbom: 요약에 단계별 소요(SBOM 생성 vs 취약점 스캔) 표시, 오해 주던 "총 소요"·
  항상 0인 per-SBOM Sec·min/max 라인 제거. 스캔한 SEVERITY 만 동적 컬럼.
- generate-sbom: 생성 소요시간을 .sbom-gen-seconds 로 기록(요약 단계별 시간용).
- doc/sbom-pipeline.md: 실행 이미지(Dockerfile)·빌드/푸시·GitHub 설정·결과 확인/대응 보강.
- .gitignore: .sbom-gen-seconds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 14:29:07 +09:00
wbsong111 d6e3d0af79 docs(sbom): add pipeline image Dockerfile + cross-reference from workflow
.github/workflows/sbom.yml 의 SBOM_PIPELINE_IMAGE 로 사용하는 실행 이미지
Dockerfile 을 doc/scripts/Dockerfile 로 추가(debian/glibc + helm/trivy/python3/git).
워크플로·sbom-pipeline.md 에서 상호 참조하도록 갱신.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 13:26:04 +09:00
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