자체 빌드 이미지 레포명을 security-images에서 hardened-containers로 정정한다

실제 레포명은 hardened-containers인데 이관 커밋 이후 문서·워크플로·차트 주석에
잘못된 이름 security-images가 남아 있었다. 텍스트 참조 전체를 정정하고
doc/migrations/의 이관 핸드오프 문서도 파일명까지 리네임했다. env var/secret
이름(SECURITY_IMAGES_REPO, SECURITY_IMAGES_DISPATCH_TOKEN)은 GitHub Secret
재등록이 필요한 별도 운영 작업이라 이번 텍스트 정정 범위에서 제외했다.

덧붙여 scripts/build/patch-catalog-tag.py의 docstring이 삭제된 build-image.yml을
호출자로 여전히 가리키고 있던 것도 실제 호출 경로(check-rebuild-needed.py /
apply-published-tags.py → catalog-tag-update.yml)로 고쳤다.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
wbsong111
2026-08-26 08:16:37 +09:00
parent 7746570ec0
commit 9e5b6633db
24 changed files with 86 additions and 85 deletions
+4 -4
View File
@@ -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)
+1 -1
View File
@@ -55,7 +55,7 @@ gh run watch --repo <org>/dip-catalog
상위 태그 교체 → 베이스 OS 교체 → 자체 빌드 → 예외 승인
```
자체 빌드로 가야 한다면 별도 레포 `security-images`에서 한다 — 그 레포의
자체 빌드로 가야 한다면 별도 레포 `hardened-containers`에서 한다 — 그 레포의
`docs/image-authoring.md`가 절차 단일 출처다. 판정 로직 상세는
`scripts/pipeline/cve-gate.py`의 모듈 docstring을 1차 출처로 본다.
+5 -5
View File
@@ -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/<image>.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] <github-actions[bot]@users.noreply.github.com>"
git push -u origin "$BRANCH"
+6 -6
View File
@@ -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 }}
+11 -11
View File
@@ -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/<image>.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`<br>`cve-edge-post.yml` | warn-only<br>**호출 안 함** | [doc/sbom-pipeline.md](doc/sbom-pipeline.md) |
| **자체 빌드** | 그 이미지를 어떻게 만드는가 | 별도 레포 `security-images` | `self-build-drift-check.yml`(탐지·트리거)<br>`catalog-tag-update.yml`(반영) | **강제**(그 레포 소유) | 그 레포의 `docs/image-authoring.md` |
| **자체 빌드** | 그 이미지를 어떻게 만드는가 | 별도 레포 `hardened-containers` | `self-build-drift-check.yml`(탐지·트리거)<br>`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)
+3 -3
View File
@@ -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` 시크릿으로 등록해야 한다. 등록 전까지 트리거 스텝은
실패한다(의도된 명시적 실패 — 조용히 넘어가지 않는다).
+5 -5
View File
@@ -1,19 +1,19 @@
# 이미지 → 차트 매핑
security-images 레포가 발행하는 자체 빌드 이미지가 이 카탈로그의 어느 차트·어느 필드를
hardened-containers 레포가 발행하는 자체 빌드 이미지가 이 카탈로그의 어느 차트·어느 필드를
가리키는지 선언한다. **이 디렉토리에 파일이 있는 이미지 이름 = 이 카탈로그가 추적하는
자체 빌드 이미지 목록**이다(`scripts/build/check-rebuild-needed.py`
`.github/workflows/catalog-tag-update.yml`이 이 목록을 기준으로 동작한다).
이관 배경: 이 정보는 원래 security-images(당시 `images/<image>/catalog.env`)에 있었다.
이관 배경: 이 정보는 원래 hardened-containers(당시 `images/<image>/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)
참고.
## 파일 형식 — `<image>.env`
`<image>`security-images 레포의 `images/<image>/` 디렉토리명과 정확히 같아야 한다
`<image>`hardened-containers 레포의 `images/<image>/` 디렉토리명과 정확히 같아야 한다
(`published.json`의 키도 같다).
| 키 | 의미 |
+2 -2
View File
@@ -9,9 +9,9 @@
" - 예외는 '위험을 수용한다'는 기록이다. 숫자를 지우는 수단으로 쓰면 목표 자체가 무의미해진다.",
"",
"예외를 늘리기 전에 먼저 검토할 것: 상위 태그로 교체 / 베이스 OS 교체 /",
"그래도 안 되면 별도 레포 security-images 에서 자체 빌드. 예외는 마지막 수단이다.",
"그래도 안 되면 별도 레포 hardened-containers 에서 자체 빌드. 예외는 마지막 수단이다.",
"자체 빌드 이미지(docker.io/paasup/*)는 그 레포도 같은 이미지를 스캔하므로,",
"그 이미지에 대한 예외는 이 파일과 security-images 레포의 cve-exceptions.json",
"그 이미지에 대한 예외는 이 파일과 hardened-containers 레포의 cve-exceptions.json",
"양쪽에 각각 등록해야 두 게이트 모두 통과한다."
],
"exceptions": [
+1 -1
View File
@@ -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`)를 그대로
+2 -2
View File
@@ -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 부터 잇는다.
@@ -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/<image>/` 8개 | 그대로(경로 보존) |
| `scripts/build/build-hardened-image.sh` | 그대로(경로 보존) |
@@ -38,15 +38,15 @@
| 경로 | 역할 |
|---|---|
| `catalog/image-map/<image>.env` | 자체 빌드 이미지 → 어느 차트의 어느 필드(`CHART_DIRS`·`TAG_STYLE`·`TAG_BLOCK`). 옛 `images/<image>/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/` 대상이 아니다.** 옛
+8 -8
View File
@@ -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` 의 외부 엔드포인트 인증 |
@@ -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
@@ -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/
@@ -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
@@ -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 다.
@@ -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).
@@ -5,7 +5,7 @@ instances: 3
postgresql:
# SUSE BCI 15.7 기반 자체 하드닝 빌드로 교체했다.
# 빌드 정의는 별도 레포 security-images 의 images/cnpg-postgresql/(이 레포에는 없다).
# 빌드 정의는 별도 레포 hardened-containers 의 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/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) 클러스터 크기
@@ -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) 되돌리는 것이 우선.
#
@@ -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` 를
+3 -3
View File
@@ -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/<image>.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 으로 이 파일에 쓴다")
+5 -5
View File
@@ -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 += ["", "</details>"]
out += ["", "> 판정 기준은 게이트와 같다 — 실효 등급 `max(벤더, NVD)` · 승인 예외 적용 · "
"기본 HIGH 이상. 재빌드는 security-images 레포의 `build-image.yml` 을 "
"기본 HIGH 이상. 재빌드는 hardened-containers 레포의 `build-image.yml` 을 "
"`workflow_dispatch` 로 부른다.", ""]
return "\n".join(out)
+2 -1
View File
@@ -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 유형)