diff --git a/.claude/skills/cve-remediation/SKILL.md b/.claude/skills/cve-remediation/SKILL.md index 28a20c1..a2f5ced 100644 --- a/.claude/skills/cve-remediation/SKILL.md +++ b/.claude/skills/cve-remediation/SKILL.md @@ -1,12 +1,12 @@ --- name: cve-remediation -description: 게이트가 카탈로그 이미지에서 차단 CVE(CRITICAL/HIGH)를 잡았을 때 태그 교체·베이스 OS 교체·자체 빌드·예외 승인 중 어느 레버를 쓸지 판단할 때 사용한다. "이 CVE 어떻게 없애", "차단 CVE 뭐부터 해야 해", "자체 빌드 가야 하나 예외 가야 하나", "게이트 실패 다음 스텝" 같은 요청이 해당한다. sbom-cve-gate 로 게이트를 해석하는 것과 security-images 레포에서 자체 빌드를 실행하는 것 사이의 결정 단계만 담당하며 둘의 절차는 복제하지 않는다. +description: 게이트가 카탈로그 이미지에서 차단 CVE(CRITICAL/HIGH)를 잡았을 때 태그 교체·베이스 OS 교체·자체 빌드·예외 승인 중 어느 레버를 쓸지 판단할 때 사용한다. "이 CVE 어떻게 없애", "차단 CVE 뭐부터 해야 해", "자체 빌드 가야 하나 예외 가야 하나", "게이트 실패 다음 스텝" 같은 요청이 해당한다. sbom-cve-gate 로 게이트를 해석하는 것과 hardened-containers 레포에서 자체 빌드를 실행하는 것 사이의 결정 단계만 담당하며 둘의 절차는 복제하지 않는다. --- # 차단 CVE 대응 절차 이 skill 은 실행하지 않는다 — 레버를 판단해 실행 skill로 넘긴다. 게이트 실행/해석은 -`sbom-cve-gate`, 자체 빌드는 **별도 레포 `security-images`**(그 레포의 +`sbom-cve-gate`, 자체 빌드는 **별도 레포 `hardened-containers`**(그 레포의 `docs/image-authoring.md`가 단일 출처), 배포 검증은 [deploy-test-procedure.md](../../deploy-test-procedure.md)가 단일 출처다 — 여기 반복 안 한다. @@ -36,7 +36,7 @@ description: 게이트가 카탈로그 이미지에서 차단 CVE(CRITICAL/HIGH) FixedVersion 이상인지, 같은 파일이 SBOM에서 컴포넌트 두 개로 잡히지 않는지(PkgPath 비교) 확인한다. 실례: keycloak `CVE-2025-59250`(mssql-jdbc jar 하나가 두 컴포넌트로 잡혀 잘린 쪽만 매칭된 오탐). 근거·만료일은 `doc/cve-exceptions.json`. -6. 자체 빌드는 별도 레포 `security-images`에서 한다 — 그 레포의 +6. 자체 빌드는 별도 레포 `hardened-containers`에서 한다 — 그 레포의 `docs/image-authoring.md`가 절차 단일 출처다. 재빌드가 필요하면 그 레포의 `build-image.yml`을 `workflow_dispatch`로 부른다(`scripts/build/check-rebuild-needed.py` 가 배포 중인 이미지를 스캔해 대상을 판단한다). 태그/베이스 OS 교체는 카탈로그 @@ -48,5 +48,5 @@ description: 게이트가 카탈로그 이미지에서 차단 CVE(CRITICAL/HIGH) ## 참고 -- 레버 실행: [sbom-cve-gate](../sbom-cve-gate/SKILL.md) · 자체 빌드는 별도 레포 `security-images` +- 레버 실행: [sbom-cve-gate](../sbom-cve-gate/SKILL.md) · 자체 빌드는 별도 레포 `hardened-containers` - 함정: [pitfalls.md](../../pitfalls.md) · 미결 사항: [MEMORY.md](../../../MEMORY.md) diff --git a/.claude/skills/sbom-cve-gate/SKILL.md b/.claude/skills/sbom-cve-gate/SKILL.md index cb5e777..13917d9 100644 --- a/.claude/skills/sbom-cve-gate/SKILL.md +++ b/.claude/skills/sbom-cve-gate/SKILL.md @@ -55,7 +55,7 @@ gh run watch --repo /dip-catalog 상위 태그 교체 → 베이스 OS 교체 → 자체 빌드 → 예외 승인 ``` -자체 빌드로 가야 한다면 별도 레포 `security-images`에서 한다 — 그 레포의 +자체 빌드로 가야 한다면 별도 레포 `hardened-containers`에서 한다 — 그 레포의 `docs/image-authoring.md`가 절차 단일 출처다. 판정 로직 상세는 `scripts/pipeline/cve-gate.py`의 모듈 docstring을 1차 출처로 본다. diff --git a/.github/workflows/catalog-tag-update.yml b/.github/workflows/catalog-tag-update.yml index 6038751..f293e98 100644 --- a/.github/workflows/catalog-tag-update.yml +++ b/.github/workflows/catalog-tag-update.yml @@ -1,13 +1,13 @@ name: catalog-tag-update -# security-images(자체 빌드 이미지 레포, public)의 `published.json` 을 읽어 카탈로그 +# hardened-containers(자체 빌드 이미지 레포, public)의 `published.json` 을 읽어 카탈로그 # values 의 이미지 태그를 갱신한다. 그 레포는 이 카탈로그를 모른다 — 게이트 PASS + push # 가 실제로 일어난 이미지의 ref 를 `published.json` 에 기록해 둘 뿐이다. "그 태그를 어느 # 차트에 반영할지" 는 이 카탈로그가 판단한다(catalog/image-map/.env). # -# public raw URL 로 읽으므로 인증이 필요 없다. security-images 쪽 시크릿·PAT 도 없다 — +# public raw URL 로 읽으므로 인증이 필요 없다. hardened-containers 쪽 시크릿·PAT 도 없다 — # 의존 방향은 카탈로그 → 이미지 단방향이다(docs/image-authoring.md "카탈로그 레포와의 -# 계약", security-images 레포). +# 계약", hardened-containers 레포). # # PR 은 자동 생성하지 않는다 — GitHub Actions 는 GITHUB_TOKEN 으로 PR 을 만들 수 없다는 # 조직 정책에 막혀 있다(build-image.yml 이 자체 빌드 축에서도 같은 제약을 받았다). @@ -23,7 +23,7 @@ permissions: contents: write env: - SECURITY_IMAGES_REPO: paasup/security-images + SECURITY_IMAGES_REPO: paasup/hardened-containers jobs: update: @@ -71,7 +71,7 @@ jobs: ")" git commit \ -m "자체 빌드 이미지 태그 갱신: $IMAGES" \ - -m "security-images 레포의 published.json(게이트 PASS + push 확인된 발행 기록)을" \ + -m "hardened-containers 레포의 published.json(게이트 PASS + push 확인된 발행 기록)을" \ -m "반영한다. 상세는 이 실행의 Job Summary 참고." \ -m "Co-Authored-By: github-actions[bot] " git push -u origin "$BRANCH" diff --git a/.github/workflows/self-build-drift-check.yml b/.github/workflows/self-build-drift-check.yml index 47f1ef7..6a2bcf5 100644 --- a/.github/workflows/self-build-drift-check.yml +++ b/.github/workflows/self-build-drift-check.yml @@ -1,11 +1,11 @@ name: self-build-drift-check -# 배포 중인 자체 빌드 이미지(security-images 레포가 만든 것)가 새 CVE 로 규정을 벗어났는지 +# 배포 중인 자체 빌드 이미지(hardened-containers 레포가 만든 것)가 새 CVE 로 규정을 벗어났는지 # 이 카탈로그가 스스로 스캔해 판정한다. "무엇이 배포 중인가"는 이 카탈로그만 안다 — -# security-images 는 자기 스스로 이 판단을 하지 않는다 -# (security-images 레포 docs/image-authoring.md "재빌드는 이 레포가 스스로 트리거하지 않는다"). +# hardened-containers 는 자기 스스로 이 판단을 하지 않는다 +# (hardened-containers 레포 docs/image-authoring.md "재빌드는 이 레포가 스스로 트리거하지 않는다"). # -# 판정(scripts/build/check-rebuild-needed.py)이 재빌드 대상이라고 하면 security-images 의 +# 판정(scripts/build/check-rebuild-needed.py)이 재빌드 대상이라고 하면 hardened-containers 의 # `build-image.yml` 을 `workflow_dispatch` 로 부른다. 그 워크플로가 실제 빌드·검증·게이트· # push·`published.json` 갱신을 한다 — 이 워크플로는 트리거만 한다. # @@ -18,7 +18,7 @@ on: - cron: '0 2 * * 1' # 매주 월요일 02:00 UTC env: - SECURITY_IMAGES_REPO: paasup/security-images + SECURITY_IMAGES_REPO: paasup/hardened-containers jobs: drift-check: @@ -60,7 +60,7 @@ jobs: print("images=" + json.dumps([r["image"] for r in rows if r["status"] == "rebuild"])) PY - - name: security-images 재빌드 트리거 + - name: hardened-containers 재빌드 트리거 if: steps.scan.outputs.images != '' && steps.scan.outputs.images != '[]' env: GH_TOKEN: ${{ secrets.SECURITY_IMAGES_DISPATCH_TOKEN }} diff --git a/CLAUDE.md b/CLAUDE.md index 0dcd631..9e579f4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -34,7 +34,7 @@ dip-catalog/ │ ├── pipeline/ # SBOM 생성 + CVE 스캔 + 게이트 판정 (sbom.yml/cve-edge-post.yml 이 쓴다) │ ├── build/ # 자체 빌드 이미지 축의 카탈로그 쪽 절반 — 드리프트 탐지 │ │ # (check-rebuild-needed.py) + 발행 태그 반영 -│ │ # (apply-published-tags.py). 빌드 자체는 security-images 레포 +│ │ # (apply-published-tags.py). 빌드 자체는 hardened-containers 레포 │ └── deploy-test/ # 배포 검증 스크립트 + fixtures (helm/kubectl 실행 전담) ├── catalog/ │ └── image-map/.env # 자체 빌드 이미지 → 차트·필드 매핑 (목록은 이 디렉토리가 단일 출처) @@ -45,7 +45,7 @@ dip-catalog/ ├── catalog-stack-classification.md # 차트 스택 분류·우선순위(P0~P2) ├── define-chart-resources.md # 차트별 Small/Medium/Large 리소스 프로파일 ├── decisions/ # ADR — 재측정으로 복원되지 않는 차트 선택 근거 - │ # (이미지 자체 빌드 ADR은 security-images 레포로 이관됨) + │ # (이미지 자체 빌드 ADR은 hardened-containers 레포로 이관됨) └── migrations/ # 레포 간 이관 핸드오프 문서 ``` @@ -150,10 +150,10 @@ python3 agent/update_catalog/skills/helm_diff/scripts/run.py \ |-------|------| | [chart-to-cnpg](.claude/skills/chart-to-cnpg/SKILL.md) | 카탈로그 차트의 내장 bitnami postgresql 서브차트를 전용 cnpg-cluster로 전환 | | [catalog-update-pipeline](.claude/skills/catalog-update-pipeline/SKILL.md) | 차트 신규 버전 감지 → diff → breaking 판정 → 문서 생성 파이프라인 실행 (`agent/update_catalog`) | -| [cve-remediation](.claude/skills/cve-remediation/SKILL.md) | 차단 CVE 대응 레버(태그 교체/베이스 OS 교체/자체 빌드/예외) 결정 — `sbom-cve-gate` 실행 또는 별도 레포 `security-images`(자체 빌드)로 위임 | +| [cve-remediation](.claude/skills/cve-remediation/SKILL.md) | 차단 CVE 대응 레버(태그 교체/베이스 OS 교체/자체 빌드/예외) 결정 — `sbom-cve-gate` 실행 또는 별도 레포 `hardened-containers`(자체 빌드)로 위임 | | [sbom-cve-gate](.claude/skills/sbom-cve-gate/SKILL.md) | SBOM 생성·CVE 스캔·게이트 판정 실행 및 결과 해석 (`scripts/pipeline`) | -자체 빌드 하드닝 이미지 추가·변경은 이 레포의 일이 아니다 — 별도 레포 `security-images` +자체 빌드 하드닝 이미지 추가·변경은 이 레포의 일이 아니다 — 별도 레포 `hardened-containers` 에서 하고, 그 레포의 `docs/image-authoring.md`가 단일 출처다(이관 배경: [doc/migrations/](doc/migrations/)). @@ -175,27 +175,27 @@ python3 agent/update_catalog/skills/helm_diff/scripts/run.py \ | 축 | 질문 | 실행 위치 | 워크플로(이 레포) | 게이트 | 단일 출처 | |----|------|----------|------------------|--------|----------| | **차트 카탈로그** | 우리가 배포하는 이미지에 무엇이 있는가 | 이 레포 | `sbom.yml`
`cve-edge-post.yml` | warn-only
**호출 안 함** | [doc/sbom-pipeline.md](doc/sbom-pipeline.md) | -| **자체 빌드** | 그 이미지를 어떻게 만드는가 | 별도 레포 `security-images` | `self-build-drift-check.yml`(탐지·트리거)
`catalog-tag-update.yml`(반영) | **강제**(그 레포 소유) | 그 레포의 `docs/image-authoring.md` | +| **자체 빌드** | 그 이미지를 어떻게 만드는가 | 별도 레포 `hardened-containers` | `self-build-drift-check.yml`(탐지·트리거)
`catalog-tag-update.yml`(반영) | **강제**(그 레포 소유) | 그 레포의 `docs/image-authoring.md` | - **차트 축은 warn-only 다** — 게이트가 실패해도 CI/PR 을 막지 않는다. 카탈로그 차트 전체가 이 게이트로 트리아지된 적이 없다. **자체 빌드 축의 게이트는 이미 강제다**(단, 그 게이트는 - 이 레포가 아니라 `security-images` 레포가 돌린다). + 이 레포가 아니라 `hardened-containers` 레포가 돌린다). - **`cve-edge-post.yml` 은 게이트를 부르지 않는다** — 같은 스캔 데이터에 판정기가 두 벌이라는 뜻이다(승인 예외·실효 등급 미적용). 외부 엔드포인트로 집계를 POST 하는 용도다. - **자체 빌드는 대응 우선순위 3번**(상위 태그 교체 → 베이스 OS 교체 → 자체 빌드 → 예외 승인). 레버 판단은 [cve-remediation](.claude/skills/cve-remediation/SKILL.md) skill 이 갖는다. - 실행은 `security-images` 레포에서 `workflow_dispatch` 로만 한다. + 실행은 `hardened-containers` 레포에서 `workflow_dispatch` 로만 한다. - **이 레포는 "무엇을 배포 중인가"만 안다.** 어느 이미지를 자체 빌드하고 있는지는 `catalog/image-map/` 이 단일 출처다. `scripts/build/check-rebuild-needed.py`(주간 `self-build-drift-check.yml`)가 배포 중인 이미지를 직접 스캔해 재빌드 대상을 판단하고, - 필요하면 `security-images` 의 `build-image.yml` 을 트리거만 한다 — 핀을 무엇으로 + 필요하면 `hardened-containers` 의 `build-image.yml` 을 트리거만 한다 — 핀을 무엇으로 올릴지는 그 레포가 판단한다. -- **카탈로그 반영은 pull 방식이다.** `security-images` 는 이 카탈로그를 모른다 — 게이트 +- **카탈로그 반영은 pull 방식이다.** `hardened-containers` 는 이 카탈로그를 모른다 — 게이트 PASS + push 성공 시 자기 레포의 `published.json` 만 갱신한다. `catalog-tag-update.yml` 이 그 파일을 public raw URL 로 읽어가 `custom-values.yaml`/`dip-values.yaml` 을 패치한다. -- 커스텀 이미지는 자체 빌드 프레임워크·이미지 정의와 함께 **별도 레포 `security-images` +- 커스텀 이미지는 자체 빌드 프레임워크·이미지 정의와 함께 **별도 레포 `hardened-containers` 로 분리됐다.** 이관 배경과 남은 결합점은 [doc/migrations/](doc/migrations/) 참고. -- 승인 예외: `doc/cve-exceptions.json`(차트 축) — `security-images` 의 `cve-exceptions.json` +- 승인 예외: `doc/cve-exceptions.json`(차트 축) — `hardened-containers` 의 `cve-exceptions.json` (자체 빌드 축)과 별도 관리되며, 같은 이미지를 양쪽이 스캔하므로 필요하면 양쪽에 각각 등록한다. 현재 미결: [MEMORY.md](MEMORY.md) diff --git a/MEMORY.md b/MEMORY.md index 3a05673..8a1f470 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -48,11 +48,11 @@ - **`argo-cd/7.8.11` 삭제 여부** — 카탈로그 차단 CVE 239건이 전부 이 동결 버전 몫이고, 지우면 게이트가 PASS 로 떨어진다. 직전 버전을 없애는 결정이라 PR #28 에서 보류했다. - **자체 빌드 이미지 레포 분리는 완료됐다** — 프레임워크·이미지 정의·ADR 이 - `security-images` 레포로 나갔다. 카탈로그 쪽은 `catalog/image-map/`(어느 차트를 + `hardened-containers` 레포로 나갔다. 카탈로그 쪽은 `catalog/image-map/`(어느 차트를 가리키는지) + `check-rebuild-needed.py`(드리프트 탐지) + `apply-published-tags.py` (발행 태그 반영)만 남았다. 배경·결합점 전체는 - [doc/migrations/](doc/migrations/self-build-images-to-security-images.md). - **아직 설정 안 된 것**: `self-build-drift-check.yml` 이 `security-images` 의 + [doc/migrations/](doc/migrations/self-build-images-to-hardened-containers.md). + **아직 설정 안 된 것**: `self-build-drift-check.yml` 이 `hardened-containers` 의 `build-image.yml` 을 트리거하려면 그 레포에 `workflow_dispatch` 권한이 있는 PAT 을 `SECURITY_IMAGES_DISPATCH_TOKEN` 시크릿으로 등록해야 한다. 등록 전까지 트리거 스텝은 실패한다(의도된 명시적 실패 — 조용히 넘어가지 않는다). diff --git a/catalog/image-map/README.md b/catalog/image-map/README.md index dbc2182..1741ac0 100644 --- a/catalog/image-map/README.md +++ b/catalog/image-map/README.md @@ -1,19 +1,19 @@ # 이미지 → 차트 매핑 -security-images 레포가 발행하는 자체 빌드 이미지가 이 카탈로그의 어느 차트·어느 필드를 +hardened-containers 레포가 발행하는 자체 빌드 이미지가 이 카탈로그의 어느 차트·어느 필드를 가리키는지 선언한다. **이 디렉토리에 파일이 있는 이미지 이름 = 이 카탈로그가 추적하는 자체 빌드 이미지 목록**이다(`scripts/build/check-rebuild-needed.py`와 `.github/workflows/catalog-tag-update.yml`이 이 목록을 기준으로 동작한다). -이관 배경: 이 정보는 원래 security-images(당시 `images//catalog.env`)에 있었다. +이관 배경: 이 정보는 원래 hardened-containers(당시 `images//catalog.env`)에 있었다. "어느 이미지를 쓰는가"는 카탈로그가 알아야 하고 "그 이미지를 어떻게 만드는가"는 -security-images 가 알아야 하므로, 레포 분리 시 이 지식을 카탈로그 쪽으로 옮겼다 — -[doc/migrations/self-build-images-to-security-images.md](../../doc/migrations/self-build-images-to-security-images.md) +hardened-containers 가 알아야 하므로, 레포 분리 시 이 지식을 카탈로그 쪽으로 옮겼다 — +[doc/migrations/self-build-images-to-hardened-containers.md](../../doc/migrations/self-build-images-to-hardened-containers.md) 참고. ## 파일 형식 — `.env` -``는 security-images 레포의 `images//` 디렉토리명과 정확히 같아야 한다 +``는 hardened-containers 레포의 `images//` 디렉토리명과 정확히 같아야 한다 (`published.json`의 키도 같다). | 키 | 의미 | diff --git a/doc/cve-exceptions.json b/doc/cve-exceptions.json index 85a2a5f..9b8ab0e 100644 --- a/doc/cve-exceptions.json +++ b/doc/cve-exceptions.json @@ -9,9 +9,9 @@ " - 예외는 '위험을 수용한다'는 기록이다. 숫자를 지우는 수단으로 쓰면 목표 자체가 무의미해진다.", "", "예외를 늘리기 전에 먼저 검토할 것: 상위 태그로 교체 / 베이스 OS 교체 /", - "그래도 안 되면 별도 레포 security-images 에서 자체 빌드. 예외는 마지막 수단이다.", + "그래도 안 되면 별도 레포 hardened-containers 에서 자체 빌드. 예외는 마지막 수단이다.", "자체 빌드 이미지(docker.io/paasup/*)는 그 레포도 같은 이미지를 스캔하므로,", - "그 이미지에 대한 예외는 이 파일과 security-images 레포의 cve-exceptions.json", + "그 이미지에 대한 예외는 이 파일과 hardened-containers 레포의 cve-exceptions.json", "양쪽에 각각 등록해야 두 게이트 모두 통과한다." ], "exceptions": [ diff --git a/doc/decisions/0003-etcd-chart-selection.md b/doc/decisions/0003-etcd-chart-selection.md index bbe0a66..c4f3961 100644 --- a/doc/decisions/0003-etcd-chart-selection.md +++ b/doc/decisions/0003-etcd-chart-selection.md @@ -35,7 +35,7 @@ dev 클러스터 `apisix` 네임스페이스에 이미 `data-apisix-etcd-0` PVC 1. 패치가 멈춘 이미지는 시간이 지날수록 미수정 CVE 가 구조적으로 누적된다 — "CRITICAL/HIGH 0건" 을 유지 가능한 상태로 지속할 수 없다. 2. 버전 고정 없는 `latest`-only 배포는 **롤링 태그 금지** 규칙과 애초에 양립하지 않는다 - (자체 빌드 이미지에 적용되는 이 규칙은 `security-images` 레포의 `docs/image-authoring.md` + (자체 빌드 이미지에 적용되는 이 규칙은 `hardened-containers` 레포의 `docs/image-authoring.md` 가 갖는다). `groundhog2k/etcd` 는 업스트림 etcd 프로젝트의 원본 이미지(`quay.io/coreos/etcd`)를 그대로 diff --git a/doc/decisions/README.md b/doc/decisions/README.md index 7cbab5f..0e41e99 100644 --- a/doc/decisions/README.md +++ b/doc/decisions/README.md @@ -10,11 +10,11 @@ CVE 건수·커버리지·패키지 버전 같은 수치는 게이트가 매 실 |---|---|---|---| | [0003](0003-etcd-chart-selection.md) | etcd 는 `groundhog2k/etcd` 단일 차트 · replicas=1 로 배포한다 | 2026-07-31 | 확정 | -**이미지 자체 빌드 ADR(0001·0002·0004)은 별도 레포 `security-images` 로 이관됐다** — +**이미지 자체 빌드 ADR(0001·0002·0004)은 별도 레포 `hardened-containers` 로 이관됐다** — 그 이미지들의 빌드 정의와 함께 그 레포의 `docs/decisions/` 에 있다. 카탈로그가 무엇을 배포하는가(차트)와 그 이미지를 어떻게 만드는가(자체 빌드)가 다른 레포에 놓이며 근거도 함께 옮긴 것이다. 이관 배경은 -[doc/migrations/self-build-images-to-security-images.md](../migrations/self-build-images-to-security-images.md). +[doc/migrations/self-build-images-to-hardened-containers.md](../migrations/self-build-images-to-hardened-containers.md). 번호가 0003 하나만 남아 이어지지 않아 보이지만, 다른 세 번호가 예약돼 있던 것일 뿐이고 새 ADR 은 0005 부터 잇는다. diff --git a/doc/migrations/self-build-images-to-security-images.md b/doc/migrations/self-build-images-to-hardened-containers.md similarity index 79% rename from doc/migrations/self-build-images-to-security-images.md rename to doc/migrations/self-build-images-to-hardened-containers.md index deee8fc..b4aab12 100644 --- a/doc/migrations/self-build-images-to-security-images.md +++ b/doc/migrations/self-build-images-to-hardened-containers.md @@ -1,7 +1,7 @@ -# 자체 빌드 하드닝 이미지 → `security-images` 레포 이관 +# 자체 빌드 하드닝 이미지 → `hardened-containers` 레포 이관 이 문서는 자체 빌드 이미지 프레임워크·이미지 정의를 별도 public 레포 -`security-images` 로 분리한 작업의 기록이다. 무엇이 어디로 갔고, 두 레포가 지금 +`hardened-containers` 로 분리한 작업의 기록이다. 무엇이 어디로 갔고, 두 레포가 지금 무엇으로 계약하는지, 아직 안 된 것이 무엇인지를 담는다. ## 배경 @@ -11,7 +11,7 @@ - **차트 카탈로그 축** — "무엇을 배포 중인가" (`manifests/helm/`, warn-only 게이트) - **자체 빌드 축** — "그 이미지를 어떻게 만드는가" (`images/`, 강제 게이트) -`security-images` 가 public 이 될 예정이라 세 조건이 붙었다: **외부 의존성 없이 +`hardened-containers` 가 public 이 될 예정이라 세 조건이 붙었다: **외부 의존성 없이 단독 동작**(클론 + `docker` + `trivy` 만으로 빌드·게이트 완결), **슬림 게이트**(이미지 판정에 불필요한 차트 축 로직 제거), **산업화**(내부 호스트명·개인 계정·이슈/PR 번호 제거). 이 조건들이 원래 `.claude/image-authoring.md` 가 적어 두었던 "레포 분리 후 @@ -20,7 +20,7 @@ ## 무엇이 옮겨갔는가 -| 카탈로그(이 레포)에 있던 것 | `security-images` 로 | +| 카탈로그(이 레포)에 있던 것 | `hardened-containers` 로 | |---|---| | `images//` 8개 | 그대로(경로 보존) | | `scripts/build/build-hardened-image.sh` | 그대로(경로 보존) | @@ -38,15 +38,15 @@ | 경로 | 역할 | |---|---| | `catalog/image-map/.env` | 자체 빌드 이미지 → 어느 차트의 어느 필드(`CHART_DIRS`·`TAG_STYLE`·`TAG_BLOCK`). 옛 `images//catalog.env` 의 카탈로그 레이아웃 정보만 뗀 것 | -| `scripts/build/check-rebuild-needed.py` | 드리프트 탐지(A 파트만) — 배포 중인 이미지가 새 CVE 로 규정을 벗어났는가. 핀 판단(B 파트)은 제거했다 — `security-images` 의 `suggest-go-upgrades.py` 가 갖는다 | -| `scripts/build/apply-published-tags.py` | `security-images` 의 `published.json` 을 카탈로그 values 에 반영 | +| `scripts/build/check-rebuild-needed.py` | 드리프트 탐지(A 파트만) — 배포 중인 이미지가 새 CVE 로 규정을 벗어났는가. 핀 판단(B 파트)은 제거했다 — `hardened-containers` 의 `suggest-go-upgrades.py` 가 갖는다 | +| `scripts/build/apply-published-tags.py` | `hardened-containers` 의 `published.json` 을 카탈로그 values 에 반영 | | `scripts/build/patch-catalog-tag.py` | 변경 없음(원래도 카탈로그 파일만 다루는 순수 도구였다) | -| `.github/workflows/self-build-drift-check.yml` | 주간, 배포 중인 이미지 스캔 → 재빌드 필요하면 `security-images` 의 `build-image.yml` 을 `workflow_dispatch` 로 트리거만 | +| `.github/workflows/self-build-drift-check.yml` | 주간, 배포 중인 이미지 스캔 → 재빌드 필요하면 `hardened-containers` 의 `build-image.yml` 을 `workflow_dispatch` 로 트리거만 | | `.github/workflows/catalog-tag-update.yml` | 매일, `published.json` 조회 → 카탈로그 values 패치 → 브랜치 push | ## 계약 — `published.json` 하나뿐 -`security-images` 는 **이 카탈로그를 모른다.** 게이트 PASS + 레지스트리 push 가 실제로 +`hardened-containers` 는 **이 카탈로그를 모른다.** 게이트 PASS + 레지스트리 push 가 실제로 일어났을 때만 자기 레포의 `published.json` 을 갱신한다: ```json @@ -55,20 +55,20 @@ `catalog-tag-update.yml` 이 이 파일을 **public raw URL** 로 읽어간다 — 인증도, 그 레포의 시크릿도 필요 없다. 의존 방향은 **카탈로그 → 이미지 단방향**이다. -`repository_dispatch` 같은 역방향 알림은 쓰지 않는다 — 그러려면 `security-images` +`repository_dispatch` 같은 역방향 알림은 쓰지 않는다 — 그러려면 `hardened-containers` 시크릿에 이 카탈로그 쓰기 권한 PAT 을 둬야 하는데, 그건 그 레포의 "외부 의존성 없이 단독 동작" 원칙과 충돌한다. ## 원래 계획과 달라진 점 -`.claude/image-authoring.md`(삭제됨, 원문은 `security-images` 의 git 히스토리에)의 +`.claude/image-authoring.md`(삭제됨, 원문은 `hardened-containers` 의 git 히스토리에)의 "레포 분리 후 무엇이 끊기는가" 는 게이트를 **composite action** 으로 공개해 두 축이 `uses:` 로 공유하는 안을 제시했다. 실제로는 그렇게 하지 않았다 — 두 가지 이유다. 1. **`suggest-go-upgrades.py` 가 `cve-gate.py` 를 `importlib` 로 모듈 로드했다.** composite action 은 워크플로 스텝만 공유하고 파이썬 모듈 임포트를 공유하지 못한다. `effective_severity` 함수를 게이트의 "정식 소유"로 옮기고(이 레포의 `cve-gate.py` · - `security-images` 의 `image-gate.py` 양쪽에 독립적으로), 두 게이트가 완전히 갈라지는 + `hardened-containers` 의 `image-gate.py` 양쪽에 독립적으로), 두 게이트가 완전히 갈라지는 쪽을 택했다. 2. **게이트 규칙 분기를 허용하기로 했다.** 차트 축은 warn-only, 자체 빌드 축은 강제라 강제력부터 다르다. 공유 action 대신 각자 자기 게이트를 소유하고, `max(벤더, NVD)` @@ -82,13 +82,13 @@ ## 아직 안 된 것 - **`SECURITY_IMAGES_DISPATCH_TOKEN` 시크릿 미등록.** `self-build-drift-check.yml` 이 - `security-images` 의 `build-image.yml` 을 `workflow_dispatch` 로 부르려면 + `hardened-containers` 의 `build-image.yml` 을 `workflow_dispatch` 로 부르려면 그 레포에 `workflow_dispatch` 권한이 있는 PAT 이 필요하다. 등록 전까지 트리거 스텝은 명시적으로 실패한다. -- **`security-images` 레포 자체가 아직 GitHub 에 없다.** 로컬 레포만 있는 상태에서 +- **`hardened-containers` 레포 자체가 아직 GitHub 에 없다.** 로컬 레포만 있는 상태에서 이 이관을 진행했다 — GitHub 레포 생성·push, `DOCKERHUB_USER`/`DOCKERHUB_TOKEN` 시크릿 등록이 선행돼야 위 두 워크플로가 실제로 동작한다. -- **`published.json` 의 `digest` 필드 대부분 공란.** `security-images` 가 아직 실제로 +- **`published.json` 의 `digest` 필드 대부분 공란.** `hardened-containers` 가 아직 실제로 이미지를 재빌드·push 하지 않아서다. 다음 빌드가 채운다 — MEMORY.md 의 "카탈로그 태그가 클러스터보다 앞서 있다" 항목이 이 필드를 쓸 계획이다. - **`manifests/applicationset/**` 는 `catalog/image-map/` 대상이 아니다.** 옛 diff --git a/doc/sbom-pipeline.md b/doc/sbom-pipeline.md index 0b96f91..46806af 100644 --- a/doc/sbom-pipeline.md +++ b/doc/sbom-pipeline.md @@ -11,9 +11,9 @@ GitHub Actions([.github/workflows/sbom.yml](../.github/workflows/sbom.yml))로 | | 다룬다 — **차트 카탈로그 축** | 다루지 않는다 — **자체 빌드 축** | |---|---|---| | 질문 | 우리가 배포하는 이미지에 무엇이 있는가 | 그 이미지를 어떻게 만드는가 | -| 실행 위치 | 이 레포 | 별도 레포 `security-images` | -| 워크플로 | `sbom.yml` · `cve-edge-post.yml` | `security-images` 의 `build-image.yml`(이 레포에서는 `self-build-drift-check.yml` 이 필요할 때 그것을 부른다) | -| 단일 출처 | **이 문서** | `security-images` 레포의 `docs/image-authoring.md` | +| 실행 위치 | 이 레포 | 별도 레포 `hardened-containers` | +| 워크플로 | `sbom.yml` · `cve-edge-post.yml` | `hardened-containers` 의 `build-image.yml`(이 레포에서는 `self-build-drift-check.yml` 이 필요할 때 그것을 부른다) | +| 단일 출처 | **이 문서** | `hardened-containers` 레포의 `docs/image-authoring.md` | **카탈로그 values 가 자체 빌드 이미지(`docker.io/paasup/*`)를 가리키므로 그 이미지도 이 문서의 스캔 대상이다** — 축이 갈린 것은 "누가 만들고 결정하는가" 이고 "누가 스캔되는가" 가 아니다. @@ -138,7 +138,7 @@ docker buildx build --platform linux/amd64 \ > 적용하지 않는다.** 같은 스캔 데이터에서 다른 숫자가 나올 수 있다. **PR 을 실제로 막는 게이트는 이 축에 없다** — `sbom.yml` 은 warn-only 다. 강제 게이트는 -자체 빌드 축(`security-images` 레포의 `images/**` PR)에만 있다. +자체 빌드 축(`hardened-containers` 레포의 `images/**` PR)에만 있다. > **`manifests/applicationset/**` 를 스캔하지 않는 것은 의도다.** 그 아래 `dip-values.yaml` 은 > dip-console 이 배포 values 를 만들 때 쓰는 **참조 파일**이고, 같은 이미지를 `manifests/helm/` @@ -195,7 +195,7 @@ Repo Secret `CVE_API_KEY`). **`sbom.yml` 에서는 아직 `--warn-only` 다** — 게이트가 실패해도 워크플로/PR 을 막지 않는다. 카탈로그 차트 전체가 아직 이 게이트로 트리아지된 적이 없어, 강제 전환 전에 먼저 전체 스캔 1회로 현황을 -파악해야 한다(`MEMORY.md`). 자체 빌드 축(`security-images` 레포의 `build-image.yml`)의 +파악해야 한다(`MEMORY.md`). 자체 빌드 축(`hardened-containers` 레포의 `build-image.yml`)의 게이트는 이미 강제다 — 단, 그 게이트는 별도 레포가 소유한다. > **커버리지 자가진단(`CoverageProbe`).** `scan-sbom.sh` 는 os-pkgs findings 가 0건인 @@ -208,11 +208,11 @@ Repo Secret `CVE_API_KEY`). ## 자체 빌드 축은 이 문서가 다루지 않는다 게이트가 상위 태그 교체·베이스 OS 교체로 해소되지 않는 차단 CVE 를 찾으면 자체 빌드로 간다. -그 축은 **별도 레포 `security-images`** 가 갖는다 — 빌드·검증·게이트·push 전부 그 레포 +그 축은 **별도 레포 `hardened-containers`** 가 갖는다 — 빌드·검증·게이트·push 전부 그 레포 안에서 이루어지고, 단일 출처는 그 레포의 `docs/image-authoring.md` 다. 이 카탈로그에는 "어느 차트가 그 이미지를 가리키는가"(`catalog/image-map/`)와 드리프트 탐지 (`scripts/build/check-rebuild-needed.py`, 주간 `self-build-drift-check.yml`)만 남아 있다 — -이관 배경은 [doc/migrations/](migrations/self-build-images-to-security-images.md). +이관 배경은 [doc/migrations/](migrations/self-build-images-to-hardened-containers.md). 이 문서가 알아야 할 것은 하나뿐이다: **자체 빌드 이미지도 카탈로그가 가리키는 한 위 스캔·게이트 대상이다.** 실제로 `docker.io/paasup/*` 가 게이트 리포트에 등장한다. @@ -224,7 +224,7 @@ Repo Secret `CVE_API_KEY`). | 종류 | 이름 | 용도 | |------|------|------| | **Variable** | `SBOM_PIPELINE_IMAGE` | 실행 이미지 태그 (예: `docker.io/paasup/sbom-pipeline:20260820`) | -| Secret | `DOCKERHUB_USER` / `DOCKERHUB_TOKEN` | **docker.io + docker.getcollate.io rate limit 회피**. getcollate(openmetadata)는 Docker Hub 프록시라 익명 pull 시 rate limit(TOOMANYREQUESTS)에 걸림 → Docker Hub 자격증명으로 인증. `security-images` 레포도 자체 push 용으로 별도 등록된 같은 이름의 시크릿을 쓴다(이 레포와는 무관하게 그 레포에 따로 등록) | +| Secret | `DOCKERHUB_USER` / `DOCKERHUB_TOKEN` | **docker.io + docker.getcollate.io rate limit 회피**. getcollate(openmetadata)는 Docker Hub 프록시라 익명 pull 시 rate limit(TOOMANYREQUESTS)에 걸림 → Docker Hub 자격증명으로 인증. `hardened-containers` 레포도 자체 push 용으로 별도 등록된 같은 이름의 시크릿을 쓴다(이 레포와는 무관하게 그 레포에 따로 등록) | | Secret | `NGC_API_KEY` | **nvcr.io 인증**(NVIDIA nemo/nim — 없으면 pull 불가) | | Secret | `CVE_API_KEY` | `cve-edge-post.yml` 의 외부 엔드포인트 인증 | diff --git a/manifests/helm/apisix/2.16.0/custom-values.yaml b/manifests/helm/apisix/2.16.0/custom-values.yaml index f527fbe..cfdf7b1 100644 --- a/manifests/helm/apisix/2.16.0/custom-values.yaml +++ b/manifests/helm/apisix/2.16.0/custom-values.yaml @@ -4,10 +4,10 @@ # 기반으로 keycloak-authz 커스텀 플러그인만 얹어 빌드했다. 이 베이스(Debian) 자체가 # CVE 게이트를 다수 차단 — 이미 최신 apache/apisix 태그라 태그 교체로도 안 없어지는 # Debian 베이스 OS 패키지 CVE라, 자체 빌드(SUSE BCI 위에 APISIX-Runtime 전체를 소스에서 -# 재현 + keycloak-authz 오버레이)로 교체했다. 빌드 정의·근거는 별도 레포 security-images +# 재현 + keycloak-authz 오버레이)로 교체했다. 빌드 정의·근거는 별도 레포 hardened-containers # 의 images/apisix/(README.md 포함) — 이 레포에는 없다. # -# 차트 업그레이드 시 이 태그도 새 appVersion 에 맞춰 security-images 에서 apisix 를 다시 +# 차트 업그레이드 시 이 태그도 새 appVersion 에 맞춰 hardened-containers 에서 apisix 를 다시 # 빌드해 갱신할 것 — dataup 레포 쪽은 더 이상 이 카탈로그가 참조하지 않는다(그 레포 # 자체는 그대로 둠). image: @@ -186,13 +186,13 @@ ingress-controller: # apisix-ingress-controller 서브차트 기본값(2.1.0, apache/apisix-ingress-controller)이 # 이미 최신 태그인데도 CVE 게이트를 다수 차단(정적 링크된 Go 모듈 다수 — 태그 교체로도 # 해소 안 됨) — 자체 빌드(취약 모듈만 강제 업그레이드)로 교체해 게이트 PASS. 빌드 - # 정의·근거는 별도 레포 security-images 의 images/apisix-ingress-controller/(이 레포에는 없다). + # 정의·근거는 별도 레포 hardened-containers 의 images/apisix-ingress-controller/(이 레포에는 없다). # # adc 사이드카 — 태그 교체는 유효한 부분 조치였지만 완전 해소는 아니었다(벤더 등급만 # 보면 통과지만 max(벤더,NVD) 로는 여전히 차단 — Debian 이 "affected, 수정 없음"으로 # 영구 고정해둔 벤더 하향 등급 사례, cnpg-postgresql 때와 같은 패턴). 자체 빌드 # (distroless 대신 SUSE BCI + nodejs24, 빌더 스테이지는 업스트림 그대로)로 교체해 - # 게이트 PASS. 빌드 정의·근거는 별도 레포 security-images 의 images/adc/(이 레포에는 없다). + # 게이트 PASS. 빌드 정의·근거는 별도 레포 hardened-containers 의 images/adc/(이 레포에는 없다). deployment: image: repository: docker.io/paasup/apisix-ingress-controller diff --git a/manifests/helm/argo-cd/10.4.0/custom-values.yaml b/manifests/helm/argo-cd/10.4.0/custom-values.yaml index b42a9d7..68b5f41 100644 --- a/manifests/helm/argo-cd/10.4.0/custom-values.yaml +++ b/manifests/helm/argo-cd/10.4.0/custom-values.yaml @@ -9,7 +9,7 @@ global: # 자체 빌드(대응 우선순위 c) — 업스트림 v3.5.1 의 차단 CVE 대부분이 바이너리에 정적 # 링크된 Go 모듈이라 상위 태그 교체·베이스 OS 교체로 해소되지 않았다. 번들 도구 # (helm/kustomize/git-lfs)까지 최신 툴체인으로 다시 컴파일했다. - # 빌드 정의·근거는 별도 레포 security-images 의 images/argocd/(이 레포에는 없다). + # 빌드 정의·근거는 별도 레포 hardened-containers 의 images/argocd/(이 레포에는 없다). # 상위 태그가 이 문제를 해결하면(대응 우선순위 a) 업스트림으로 되돌리는 것이 우선이다. # # 이 값은 argocd 바이너리를 쓰는 5개 컴포넌트(server/repo-server/application-controller/ diff --git a/manifests/helm/cloudnative-pg/0.29.0/custom-values.yaml b/manifests/helm/cloudnative-pg/0.29.0/custom-values.yaml index 996baee..6b8bd30 100644 --- a/manifests/helm/cloudnative-pg/0.29.0/custom-values.yaml +++ b/manifests/helm/cloudnative-pg/0.29.0/custom-values.yaml @@ -4,7 +4,7 @@ image: # 자체 빌드(대응 우선순위 c) — 업스트림 1.30.0 이 게이트 차단 HIGH 3건(stdlib·x/text·grpc, # Go 모듈 정적 링크라 베이스 OS 교체로 해소 불가)으로 막혀 release-1.30 브랜치를 직접 - # 컴파일했다. 빌드 정의·근거·결정은 별도 레포 security-images 의 images/cloudnative-pg/ + # 컴파일했다. 빌드 정의·근거·결정은 별도 레포 hardened-containers 의 images/cloudnative-pg/ # 와 docs/decisions/0002-cloudnative-pg-operator-self-build.md(이 레포에는 없다). # 상위 태그가 나오면(대응 우선순위 a) 되돌리는 것이 우선. repository: docker.io/paasup/cloudnative-pg diff --git a/manifests/helm/cnpg-cluster/1.0.0/custom-values.yaml b/manifests/helm/cnpg-cluster/1.0.0/custom-values.yaml index b17232c..e118866 100644 --- a/manifests/helm/cnpg-cluster/1.0.0/custom-values.yaml +++ b/manifests/helm/cnpg-cluster/1.0.0/custom-values.yaml @@ -5,12 +5,12 @@ instances: 3 postgresql: # SUSE BCI 15.7 기반 자체 하드닝 빌드로 교체했다. - # 결정 근거·받아들인 비용·빌드 정의는 별도 레포 security-images 의 + # 결정 근거·받아들인 비용·빌드 정의는 별도 레포 hardened-containers 의 # docs/decisions/0001-cnpg-postgresql-image.md 와 images/cnpg-postgresql/ # (이 레포에는 없다). # # 태그에 빌드일을 포함한다. 같은 앱 버전이라도 베이스 업데이트 결과가 시점마다 다르므로 - # 롤링 태그를 쓰지 않는다(security-images 레포의 docs/image-authoring.md). + # 롤링 태그를 쓰지 않는다(hardened-containers 레포의 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 다. diff --git a/manifests/helm/cnpg-cluster/1.0.0/dip-values.yaml b/manifests/helm/cnpg-cluster/1.0.0/dip-values.yaml index cbf471e..51f5578 100644 --- a/manifests/helm/cnpg-cluster/1.0.0/dip-values.yaml +++ b/manifests/helm/cnpg-cluster/1.0.0/dip-values.yaml @@ -4,7 +4,7 @@ instances: 3 postgresql: # custom-values.yaml 과 동일하게 SUSE BCI 15.7 자체 빌드를 쓴다. - # 근거·비용은 별도 레포 security-images 의 docs/decisions/0001-cnpg-postgresql-image.md + # 근거·비용은 별도 레포 hardened-containers 의 docs/decisions/0001-cnpg-postgresql-image.md # (이 레포에는 없다). # trivy 는 SLES 15.7 을 정상 커버한다(게이트의 CoverageProbe 가 매 스캔마다 확인 — # doc/sbom-pipeline.md). diff --git a/manifests/helm/cnpg-cluster/1.1.0/custom-values.yaml b/manifests/helm/cnpg-cluster/1.1.0/custom-values.yaml index 90ac94f..7f3bad1 100644 --- a/manifests/helm/cnpg-cluster/1.1.0/custom-values.yaml +++ b/manifests/helm/cnpg-cluster/1.1.0/custom-values.yaml @@ -5,7 +5,7 @@ instances: 3 postgresql: # SUSE BCI 15.7 기반 자체 하드닝 빌드로 교체했다. - # 빌드 정의는 별도 레포 security-images 의 images/cnpg-postgresql/(이 레포에는 없다). + # 빌드 정의는 별도 레포 hardened-containers 의 images/cnpg-postgresql/(이 레포에는 없다). # # 태그에 빌드일을 포함한다. 같은 앱 버전이라도 베이스 업데이트 결과가 시점마다 다르므로 # 롤링 태그를 쓰지 않는다. diff --git a/manifests/helm/etcd/1.1.12/CUSTOM-README.md b/manifests/helm/etcd/1.1.12/CUSTOM-README.md index b6ed4a9..bc02d04 100644 --- a/manifests/helm/etcd/1.1.12/CUSTOM-README.md +++ b/manifests/helm/etcd/1.1.12/CUSTOM-README.md @@ -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/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` (태그 미지정) | +| `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`)으로 막혀 대체했다. 빌드 정의·근거·채택 결정 배경은 별도 레포 `hardened-containers` 의 `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) 클러스터 크기 diff --git a/manifests/helm/etcd/1.1.12/custom-values.yaml b/manifests/helm/etcd/1.1.12/custom-values.yaml index 77d599a..6b61b87 100644 --- a/manifests/helm/etcd/1.1.12/custom-values.yaml +++ b/manifests/helm/etcd/1.1.12/custom-values.yaml @@ -6,7 +6,7 @@ image: # HIGH 1건(golang.org/x/text, CVE-2026-56852, 바이너리 정적 링크라 베이스 OS 교체로 # 해소 불가)으로 막혀 v3.7.1 태그가 가리키는 commit 을 그대로 컴파일했다. x/text 만 # go.work 워크스페이스 전역 replace 로 0.39.0 이상으로 강제. - # 근거·결정·빌드 정의는 별도 레포 security-images 의 docs/decisions/0004-etcd-image-self-build.md + # 근거·결정·빌드 정의는 별도 레포 hardened-containers 의 docs/decisions/0004-etcd-image-self-build.md # 와 images/etcd/(이 레포에는 없다). 상위 태그가 나오거나 release-3.7 에 백포트되면 # (대응 우선순위 a) 되돌리는 것이 우선. # diff --git a/manifests/helm/keycloakx/7.2.2/CUSTOM-README.md b/manifests/helm/keycloakx/7.2.2/CUSTOM-README.md index eb77d82..3d3112e 100644 --- a/manifests/helm/keycloakx/7.2.2/CUSTOM-README.md +++ b/manifests/helm/keycloakx/7.2.2/CUSTOM-README.md @@ -125,7 +125,7 @@ proxy: `image.repository`/`image.tag` 는 업스트림 `quay.io/keycloak/keycloak` 이 아니라 `docker.io/paasup/keycloak` 자체 빌드 하드닝 이미지를 가리킨다. 빌드 정의와, 왜 자체 -빌드인지·업스트림과 무엇이 다른지는 별도 레포 `security-images` 의 `images/keycloak/` +빌드인지·업스트림과 무엇이 다른지는 별도 레포 `hardened-containers` 의 `images/keycloak/` (`README.md` 포함)가 단일 출처다 — 이 레포에는 없다. 배포 관점에서 알아야 할 것만 아래에 적는다. @@ -155,7 +155,7 @@ proxy: ### 이미지 갱신 -`security-images` 레포의 `images/keycloak/suse.build.env` 의 `KEYCLOAK_VERSION` 과 +`hardened-containers` 레포의 `images/keycloak/suse.build.env` 의 `KEYCLOAK_VERSION` 과 jar 오버레이 버전을 사람이 고쳐 커밋하는 것이 갱신 트리거다(그 레포에서). 그 레포의 `build-image.yml` 이 빌드·게이트 통과 후 push 하면 `published.json` 이 갱신되고, 이 카탈로그의 `catalog-tag-update.yml` 이 그것을 읽어가 이 파일의 `image.tag` 를 diff --git a/scripts/build/apply-published-tags.py b/scripts/build/apply-published-tags.py index 38c28a1..6b888c9 100644 --- a/scripts/build/apply-published-tags.py +++ b/scripts/build/apply-published-tags.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -"""apply-published-tags.py — security-images 의 `published.json` 을 읽어 카탈로그 +"""apply-published-tags.py — hardened-containers 의 `published.json` 을 읽어 카탈로그 values 의 자체 빌드 이미지 태그를 갱신한다. -카탈로그와 security-images(자체 빌드 이미지 레포)의 계약은 `published.json` 파일 +카탈로그와 hardened-containers(자체 빌드 이미지 레포)의 계약은 `published.json` 파일 스키마 하나뿐이다 — 그 레포는 게이트 PASS + push 가 실제로 일어났을 때만 이 파일을 갱신한다. 이 스크립트는 그 파일과 `catalog/image-map/.env`(어느 차트의 어느 필드를 갱신할지)를 대조해 `custom-values.yaml`/`dip-values.yaml` 을 패치한다. @@ -105,7 +105,7 @@ def apply_for_image(image, new_ref, dry_run): def main(): ap = argparse.ArgumentParser(description=__doc__) ap.add_argument("--published", required=True, metavar="FILE", - help="security-images 의 published.json (로컬 경로 — 원격 조회는 호출자가 한다)") + help="hardened-containers 의 published.json (로컬 경로 — 원격 조회는 호출자가 한다)") ap.add_argument("--image", default="", help="이 이미지만 반영 (기본: published.json 의 전체)") ap.add_argument("--dry-run", action="store_true", help="무엇이 바뀔지 보고만 하고 파일은 건드리지 않는다") ap.add_argument("--json-out", metavar="FILE", help="변경 목록을 JSON 으로 이 파일에 쓴다") diff --git a/scripts/build/check-rebuild-needed.py b/scripts/build/check-rebuild-needed.py index 56df6bb..f30c16f 100644 --- a/scripts/build/check-rebuild-needed.py +++ b/scripts/build/check-rebuild-needed.py @@ -38,10 +38,10 @@ 레포 분리 이후 — 이 스크립트는 절반이다 ---------------------------------------- -커스텀 이미지는 security-images(별도 레포)로 나갔다. "무엇을 배포 중인가"는 이 카탈로그가 -알고, "그 이미지를 어떻게 만드는가"(핀 판단·재빌드)는 security-images 가 안다. 이 스크립트는 +커스텀 이미지는 hardened-containers(별도 레포)로 나갔다. "무엇을 배포 중인가"는 이 카탈로그가 +알고, "그 이미지를 어떻게 만드는가"(핀 판단·재빌드)는 hardened-containers 가 안다. 이 스크립트는 **탐지만** 한다 — 재빌드가 필요하다고 판단되면 `self-build-drift-check.yml` 이 -security-images 의 `build-image.yml` 을 `workflow_dispatch` 로 부른다. 핀을 무엇으로 +hardened-containers 의 `build-image.yml` 을 `workflow_dispatch` 로 부른다. 핀을 무엇으로 올릴지는 그 레포의 `suggest-go-upgrades.py --apply` 가 한다. 사용 @@ -201,7 +201,7 @@ def render_md(results): out.append(f"배포 중인 자체 빌드 이미지 {len(ok)}개에 차단 CVE 가 없다.") if rebuild: out += [f"**{len(rebuild)}개 이미지가 재빌드 대상이다.** 차단 CVE 에 수정 버전이 있다 " - "— security-images 레포에서 재빌드하면 해소될 가능성이 높다. 핀 조정이 " + "— hardened-containers 레포에서 재빌드하면 해소될 가능성이 높다. 핀 조정이 " "필요한지는 그 레포의 `suggest-go-upgrades.py` 가 판단한다.", "", "| 이미지 | 현재 ref | 차단 | 수정 가능 | 패키지 |", "|---|---|---:|---:|---|"] @@ -228,7 +228,7 @@ def render_md(results): out += ["", ""] out += ["", "> 판정 기준은 게이트와 같다 — 실효 등급 `max(벤더, NVD)` · 승인 예외 적용 · " - "기본 HIGH 이상. 재빌드는 security-images 레포의 `build-image.yml` 을 " + "기본 HIGH 이상. 재빌드는 hardened-containers 레포의 `build-image.yml` 을 " "`workflow_dispatch` 로 부른다.", ""] return "\n".join(out) diff --git a/scripts/build/patch-catalog-tag.py b/scripts/build/patch-catalog-tag.py index 20aa651..01e7070 100755 --- a/scripts/build/patch-catalog-tag.py +++ b/scripts/build/patch-catalog-tag.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 """카탈로그 values 파일의 자체 빌드 이미지 태그를 갱신한다. -build-image.yml 이 호출한다. 카탈로그가 실제로 쓰는 두 표기 스타일을 지원한다: +check-rebuild-needed.py / apply-published-tags.py 가 `catalog-tag-update.yml` 경유로 +호출한다. 카탈로그가 실제로 쓰는 두 표기 스타일을 지원한다: - imageName: 단일 필드 문자열 (cnpg-cluster 유형 — `imageName: "repo:tag"`) - split: image:/initImage: 등 블록 아래 registry/repository/tag 세 필드로 분리 (cloudnative-pg, etcd 유형)