자체 빌드 이미지 프레임워크를 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>
This commit is contained in:
wbsong111
2026-08-24 15:21:29 +09:00
parent e948436f53
commit 7746570ec0
87 changed files with 693 additions and 5554 deletions
+15 -17
View File
@@ -2,13 +2,14 @@
#
# 기존엔 dataup experiment/apisix/apisix-plugin 레포에서 apache/apisix:3.17.0-debian
# 기반으로 keycloak-authz 커스텀 플러그인만 얹어 빌드했다. 이 베이스(Debian) 자체가
# CVE 게이트 차단 26건(2026-08-11 실측) — 이미 최신 apache/apisix 태그라 태그 교체로도
# 안 없어지는 Debian 베이스 OS 패키지 CVE라, images/apisix 자체 빌드(SUSE BCI 위에
# APISIX-Runtime 전체를 소스에서 재현 + keycloak-authz 오버레이)로 교체했다.
# 게이트 PASS(실효 CRITICAL/HIGH 0/0, 2026-08-12 실측). 근거: images/apisix/README.md.
# CVE 게이트를 다수 차단 — 이미 최신 apache/apisix 태그라 태그 교체로도 안 없어지는
# Debian 베이스 OS 패키지 CVE라, 자체 빌드(SUSE BCI 위에 APISIX-Runtime 전체를 소스에서
# 재현 + keycloak-authz 오버레이)로 교체했다. 빌드 정의·근거는 별도 레포 security-images
# images/apisix/(README.md 포함) — 이 레포에는 없다.
#
# 차트 업그레이드 시 이 태그도 새 appVersion 에 맞춰 images/apisix 를 다시 빌드해 갱신할 것 —
# dataup 레포 쪽은 더 이상 이 카탈로그가 참조하지 않는다(그 레포 자체는 그대로 둠).
# 차트 업그레이드 시 이 태그도 새 appVersion 에 맞춰 security-images 에서 apisix 를 다시
# 빌드해 갱신할 것 — dataup 레포 쪽은 더 이상 이 카탈로그가 참조하지 않는다(그 레포
# 자체는 그대로 둠).
image:
repository: docker.io/paasup/apisix
tag: "3.17.0-security-hardened-20260813"
@@ -183,18 +184,15 @@ ingress-controller:
ingressClass: apisix # Kong의 'kong' class와 분리
# apisix-ingress-controller 서브차트 기본값(2.1.0, apache/apisix-ingress-controller)이
# 이미 최신 태그인데도 CVE 게이트 차단 25건(정적 링크된 Go 모듈 21건 — 태그 교체로도
# 해소 안 됨) — images/apisix-ingress-controller 자체 빌드(취약 모듈만 강제 업그레이드)
# 로 교체해 게이트 PASS(실효 CRITICAL/HIGH 0건, 2026-08-11 실측). 근거: images/
# apisix-ingress-controller/README.md.
# 이미 최신 태그인데도 CVE 게이트를 다수 차단(정적 링크된 Go 모듈 다수 — 태그 교체로도
# 해소 안 됨) — 자체 빌드(취약 모듈만 강제 업그레이드)로 교체해 게이트 PASS. 빌드
# 정의·근거는 별도 레포 security-images 의 images/apisix-ingress-controller/(이 레포에는 없다).
#
# adc 사이드카 — 0.27.1 → 0.29.0 태그 교체는 유효한 부분 조치였지만 완전 해소는
# 아니었다(2026-08-12 게이트 재검증에서 정정 — 벤더 등급만 보면 0/0 이지만
# max(벤더,NVD) 로는 glibc regex/collating 스택오버플로 4건이 실효 CRITICAL/HIGH 로
# 차단. Debian 이 "affected, 수정 없음"으로 영구 고정해둔 벤더 하향 등급 사례 —
# cnpg-postgresql 때와 같은 패턴). images/adc 자체 빌드(distroless 대신 SUSE BCI +
# nodejs24, 빌더 스테이지는 업스트림 그대로)로 교체해 게이트 PASS(실효 CRITICAL/HIGH
# 0/0, 2026-08-12 실측). 근거: images/adc/README.md.
# adc 사이드카 — 태그 교체는 유효한 부분 조치였지만 완전 해소는 아니었다(벤더 등급만
# 보면 통과지만 max(벤더,NVD) 로는 여전히 차단 — Debian 이 "affected, 수정 없음"으로
# 영구 고정해둔 벤더 하향 등급 사례, cnpg-postgresql 때와 같은 패턴). 자체 빌드
# (distroless 대신 SUSE BCI + nodejs24, 빌더 스테이지는 업스트림 그대로)로 교체해
# 게이트 PASS. 빌드 정의·근거는 별도 레포 security-images 의 images/adc/(이 레포에는 없다).
deployment:
image:
repository: docker.io/paasup/apisix-ingress-controller
@@ -9,8 +9,8 @@ global:
# 자체 빌드(대응 우선순위 c) — 업스트림 v3.5.1 의 차단 CVE 대부분이 바이너리에 정적
# 링크된 Go 모듈이라 상위 태그 교체·베이스 OS 교체로 해소되지 않았다. 번들 도구
# (helm/kustomize/git-lfs)까지 최신 툴체인으로 다시 컴파일했다.
# 빌드 정의: images/argocd/. 상위 태그가 이 문제를 해결하면(대응 우선순위 a)
# 업스트림으로 되돌리는 것이 우선이다.
# 빌드 정의·근거는 별도 레포 security-images 의 images/argocd/(이 레포에는 없다).
# 상위 태그가 이 문제를 해결하면(대응 우선순위 a) 업스트림으로 되돌리는 것이 우선이다.
#
# 이 값은 argocd 바이너리를 쓰는 5개 컴포넌트(server/repo-server/application-controller/
# applicationset/notifications)가 공유한다 — 컴포넌트별 image 블록이 비면 global 을
@@ -4,8 +4,9 @@
image:
# 자체 빌드(대응 우선순위 c) — 업스트림 1.30.0 이 게이트 차단 HIGH 3건(stdlib·x/text·grpc,
# Go 모듈 정적 링크라 베이스 OS 교체로 해소 불가)으로 막혀 release-1.30 브랜치를 직접
# 컴파일했다. 근거·결정: doc/decisions/0002-cloudnative-pg-operator-self-build.md.
# 빌드 정의: images/cloudnative-pg/. 상위 태그가 나오면(대응 우선순위 a) 되돌리는 것이 우선.
# 컴파일했다. 빌드 정의·근거·결정은 별도 레포 security-images 의 images/cloudnative-pg/
# 와 docs/decisions/0002-cloudnative-pg-operator-self-build.md(이 레포에는 없다).
# 상위 태그가 나오면(대응 우선순위 a) 되돌리는 것이 우선.
repository: docker.io/paasup/cloudnative-pg
tag: "1.30.0-security-hardened-20260820"
@@ -4,12 +4,13 @@
instances: 3
postgresql:
# SUSE BCI 15.7 기반 자체 하드닝 빌드로 교체했다 (2026-07-28).
# 결정 근거·받아들인 비용 → doc/decisions/0001-cnpg-postgresql-image.md
# 빌드 정의 → images/cnpg-postgresql/suse.Dockerfile + suse.build.env
# SUSE BCI 15.7 기반 자체 하드닝 빌드로 교체했다.
# 결정 근거·받아들인 비용·빌드 정의는 별도 레포 security-images 의
# docs/decisions/0001-cnpg-postgresql-image.md 와 images/cnpg-postgresql/
# (이 레포에는 없다).
#
# 태그에 빌드일을 포함한다. 같은 앱 버전이라도 베이스 업데이트 결과가 시점마다 다르므로
# 롤링 태그를 쓰지 않는다 (.claude/image-authoring.md).
# 롤링 태그를 쓰지 않는다(security-images 레포의 docs/image-authoring.md).
imageName: "docker.io/paasup/cnpg-postgresql:18.4-bci15.7-hardened-20260820"
#
# trivy 는 SLES 15.7 을 정상 커버한다 — 실효 C/H 0/0 은 측정된 결과이며 게이트 PASS 다.
@@ -4,7 +4,8 @@ instances: 3
postgresql:
# custom-values.yaml 과 동일하게 SUSE BCI 15.7 자체 빌드를 쓴다.
# 근거·비용 doc/decisions/0001-cnpg-postgresql-image.md
# 근거·비용은 별도 레포 security-images 의 docs/decisions/0001-cnpg-postgresql-image.md
# (이 레포에는 없다).
# trivy 는 SLES 15.7 을 정상 커버한다(게이트의 CoverageProbe 가 매 스캔마다 확인 —
# doc/sbom-pipeline.md).
# 실효 C/H 0/0, 게이트 PASS.
@@ -4,8 +4,8 @@
instances: 3
postgresql:
# SUSE BCI 15.7 기반 자체 하드닝 빌드로 교체했다 (2026-07-28).
# 빌드 정의 → images/cnpg-postgresql/suse.Dockerfile + suse.build.env
# SUSE BCI 15.7 기반 자체 하드닝 빌드로 교체했다.
# 빌드 정의는 별도 레포 security-images 의 images/cnpg-postgresql/(이 레포에는 없다).
#
# 태그에 빌드일을 포함한다. 같은 앱 버전이라도 베이스 업데이트 결과가 시점마다 다르므로
# 롤링 태그를 쓰지 않는다.
+1 -1
View File
@@ -52,7 +52,7 @@ kubectl -n etcd-system exec etcd-0 -- etcdctl endpoint health --cluster
| Name | 설명 | 기본값 |
| --- | --- | --- |
| `image.registry` / `image.repository` / `image.tag` | etcd 본체 이미지. **자체 빌드**(`docker.io/wbsong111/etcd:3.7.1-security-hardened-20260731`) — 업스트림 `quay.io/coreos/etcd:v3.7.1` 이 게이트 차단 HIGH 1건(`CVE-2026-56852`, `golang.org/x/text`)으로 막혀 대체했다. 근거·빌드 정의는 [images/etcd/README.md](../../../images/etcd/README.md), 채택 결정 배경은 security-catalog 프로젝트 decisions/0007(dip-catalog 미이관). 상위 태그가 나오거나 `release-3.7` 에 백포트되면 업스트림으로 되돌리는 것이 우선(대응 우선순위 a) | 업스트림 `quay.io/coreos/etcd` (태그 미지정) |
| `image.registry` / `image.repository` / `image.tag` | etcd 본체 이미지. **자체 빌드**(`docker.io/paasup/etcd:3.7.1-security-hardened-20260820`) — 업스트림 `quay.io/coreos/etcd:v3.7.1` 이 게이트 차단 HIGH 1건(`CVE-2026-56852`, `golang.org/x/text`)으로 막혀 대체했다. 빌드 정의·근거·채택 결정 배경은 별도 레포 `security-images` 의 `images/etcd/README.md` 와 `docs/decisions/0004-etcd-image-self-build.md`(이 레포에는 없다). 상위 태그가 나오거나 `release-3.7` 에 백포트되면 업스트림으로 되돌리는 것이 우선(대응 우선순위 a) | 업스트림 `quay.io/coreos/etcd` (태그 미지정) |
| `initImage.registry` / `initImage.repository` / `initImage.tag` | 데이터 디렉토리 초기화용 init 컨테이너. 업스트림 기본값(`busybox:stable`)은 롤링 태그라 `busybox:1.38.0-uclibc` 로 고정 | 업스트림 `busybox:stable` |
### 2) 클러스터 크기
@@ -6,8 +6,9 @@ image:
# HIGH 1건(golang.org/x/text, CVE-2026-56852, 바이너리 정적 링크라 베이스 OS 교체로
# 해소 불가)으로 막혀 v3.7.1 태그가 가리키는 commit 을 그대로 컴파일했다. x/text 만
# go.work 워크스페이스 전역 replace 로 0.39.0 이상으로 강제.
# 근거·결정: doc/decisions/0004-etcd-image-self-build.md. 빌드 정의: images/etcd/.
# 상위 태그가 나오거나 release-3.7 에 백포트되면(대응 우선순위 a) 되돌리는 것이 우선.
# 근거·결정·빌드 정의는 별도 레포 security-images 의 docs/decisions/0004-etcd-image-self-build.md
# 와 images/etcd/(이 레포에는 없다). 상위 태그가 나오거나 release-3.7 에 백포트되면
# (대응 우선순위 a) 되돌리는 것이 우선.
#
# 이전 값: quay.io/coreos/etcd:v3.7.1 (업스트림). etcd 프로젝트는 3.8부터
# gcr.io/etcd-development·quay.io/coreos 를 폐지하고 registry.k8s.io/etcd 로 이전
@@ -17,7 +18,7 @@ image:
tag: "3.7.1-security-hardened-20260820"
initImage:
# 업스트림 기본값 "stable" 은 롤링 태그다 (롤링 태그 금지 — .claude/image-authoring.md).
# 업스트림 기본값 "stable" 은 롤링 태그다 — 스캔 대상이 시점마다 달라지므로 고정한다.
# 이 init 컨테이너도 extract-helm-images.sh 에 잡혀 게이트 대상이 되므로 고정한다.
registry: "docker.io"
repository: "busybox"
@@ -124,10 +124,10 @@ proxy:
## 3. 자체 빌드 이미지
`image.repository`/`image.tag` 는 업스트림 `quay.io/keycloak/keycloak` 이 아니라
`docker.io/paasup/keycloak` 자체 빌드 하드닝 이미지를 가리킨다. 빌드 정의
[`images/keycloak/`](../../../../images/keycloak/) 에 있고, 왜 자체 빌드인지·업스트림과
무엇이 다른지는 [`images/keycloak/README.md`](../../../../images/keycloak/README.md) 가
단일 출처다. 배포 관점에서 알아야 할 것만 아래에 적는다.
`docker.io/paasup/keycloak` 자체 빌드 하드닝 이미지를 가리킨다. 빌드 정의와, 왜 자체
빌드인지·업스트림과 무엇이 다른지는 별도 레포 `security-images``images/keycloak/`
(`README.md` 포함)가 단일 출처다 — 이 레포에는 없다. 배포 관점에서 알아야 할 것만
아래에 적는다.
### 앱 버전이 차트 `appVersion` 과 다르다
@@ -155,6 +155,8 @@ proxy:
### 이미지 갱신
`images/keycloak/suse.build.env``KEYCLOAK_VERSION` jar 오버레이 버전을 사람이
고쳐 PR 을 여는 것이 갱신 트리거다. `build-image.yml``workflow_dispatch` 로 돌리면
빌드·게이트 통과 후 이 파일의 `image.tag` 가 자동 갱신된 브랜치가 생성된다.
`security-images` 레포의 `images/keycloak/suse.build.env``KEYCLOAK_VERSION`
jar 오버레이 버전을 사람이 고쳐 커밋하는 것이 갱신 트리거다(그 레포에서). 그 레포의
`build-image.yml` 이 빌드·게이트 통과 후 push 하면 `published.json` 이 갱신되고,
이 카탈로그의 `catalog-tag-update.yml` 이 그것을 읽어가 이 파일의 `image.tag`
자동 갱신한 브랜치를 이 레포에 만든다.