파이프라인을 두 축으로 갈라 소유 문서를 확정한다
"파이프라인이 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>
This commit is contained in:
+47
-46
@@ -4,6 +4,20 @@
|
||||
결정론적으로 생성하는 파이프라인. helm/trivy/python3 가 설치된 리눅스 컨테이너 안에서 실행하며,
|
||||
GitHub Actions([.github/workflows/sbom.yml](../.github/workflows/sbom.yml))로 자동화한다.
|
||||
|
||||
## 이 문서가 다루는 축
|
||||
|
||||
카탈로그의 CVE 파이프라인은 **두 축**이고 이 문서는 그중 하나만 다룬다.
|
||||
|
||||
| | 다룬다 — **차트 카탈로그 축** | 다루지 않는다 — **자체 빌드 축** |
|
||||
|---|---|---|
|
||||
| 질문 | 우리가 배포하는 이미지에 무엇이 있는가 | 그 이미지를 어떻게 만드는가 |
|
||||
| 워크플로 | `sbom.yml` · `cve-edge-post.yml` | `build-image.yml` |
|
||||
| 단일 출처 | **이 문서** | [.claude/image-authoring.md](../.claude/image-authoring.md) |
|
||||
|
||||
**카탈로그 values 가 자체 빌드 이미지(`docker.io/paasup/*`)를 가리키므로 그 이미지도 이 문서의
|
||||
스캔 대상이다** — 축이 갈린 것은 "누가 만들고 결정하는가" 이고 "누가 스캔되는가" 가 아니다.
|
||||
자체 빌드 이미지도 카탈로그가 배포하는 한 여기서 판정된다.
|
||||
|
||||
## 왜 필요한가
|
||||
|
||||
GitHub Dependency-Graph SBOM(예: `paasup_dip-catalog_199087.json`)은 pypi 등 소스 매니페스트만 담고
|
||||
@@ -106,7 +120,26 @@ docker buildx build --platform linux/amd64 \
|
||||
> credsStore(Docker Desktop) 환경에서 `docker-container` 빌더로 `--push` 시 인증 실패하면,
|
||||
> 단일 아키텍처를 로컬 적재(`--load`) 후 `docker push` 하거나 인라인 토큰 config 를 쓴다.
|
||||
|
||||
## CI (`.github/workflows/sbom.yml`)
|
||||
## CI — 이 축의 워크플로 2개
|
||||
|
||||
같은 스크립트(`extract` → `generate-sbom` → `scan-sbom`)와 같은 실행 이미지를 쓰지만 **뒤가 다르다.**
|
||||
|
||||
| | `sbom.yml` | `cve-edge-post.yml` |
|
||||
|---|---|---|
|
||||
| 목적 | 게이트 판정 | 외부 엔드포인트로 집계 POST |
|
||||
| PR 트리거 | `manifests/helm/**` | **없음** |
|
||||
| schedule | 일 18:00 UTC | **주석 처리** (수동만) |
|
||||
| **게이트** | `cve-gate.py` **`--warn-only`** | **호출하지 않음** |
|
||||
| 산출 | 아티팩트 `sbom-and-vuln-report` | `cve-summary.json` → POST |
|
||||
|
||||
> **판정기가 두 벌이라는 뜻이다.** `cve-edge-post.yml` 은 집계를 워크플로 YAML 안의 인라인
|
||||
> python 으로 갖고 있어 **승인 예외(`cve-exceptions.json`)도 실효 등급(`max(벤더,NVD)`)도
|
||||
> 적용하지 않는다.** 같은 스캔 데이터에서 다른 숫자가 나올 수 있다.
|
||||
|
||||
**PR 을 실제로 막는 게이트는 `images/**` 를 건드린 PR 에만 있다** — 이 축의 `sbom.yml` 은
|
||||
warn-only 이고, `manifests/applicationset/**` 는 **어떤 워크플로도 보지 않는다.**
|
||||
|
||||
### `sbom.yml` 스캔 범위
|
||||
|
||||
| 트리거 | 스캔 범위 |
|
||||
|--------|----------|
|
||||
@@ -133,14 +166,13 @@ gh workflow run helm-catalog-sbom --repo <org>/dip-catalog # 전체
|
||||
gh run watch --repo <org>/dip-catalog
|
||||
```
|
||||
|
||||
### 다른 워크플로 — `cve-edge-post.yml`
|
||||
### `cve-edge-post.yml` 상세
|
||||
|
||||
같은 스크립트·같은 실행 이미지를 쓰지만 **목적이 다르다.** `(catalog, version, image)` 단위 취약점
|
||||
건수 + CRITICAL 설명을 **단일 JSON 으로 만들어 외부 엔드포인트
|
||||
(`https://edge.gke.paasup.io/api/v1/cve-scans`)로 POST** 한다(`X-CVE-API-Key`, Repo Secret `CVE_API_KEY`).
|
||||
**게이트 판정은 하지 않는다.**
|
||||
`(catalog, version, image)` 단위 취약점 건수 + CRITICAL 설명을 **단일 JSON 으로 만들어 외부
|
||||
엔드포인트(`https://edge.gke.paasup.io/api/v1/cve-scans`)로 POST** 한다(`X-CVE-API-Key`,
|
||||
Repo Secret `CVE_API_KEY`).
|
||||
|
||||
- 트리거는 `workflow_dispatch` 뿐 — `chart`(빈 값=전체) · `limit` 입력. `schedule` 은 주석 처리 상태다.
|
||||
- 트리거는 `workflow_dispatch` 뿐 — `chart`(빈 값=전체) · `limit` 입력.
|
||||
- 이미지 하나가 여러 `manifests/helm/<name>/<version>/` 에서 재사용되면 그 조합 수만큼 항목이 중복된다
|
||||
(의도된 동작 — 소비 측이 카탈로그 단위로 집계한다).
|
||||
|
||||
@@ -161,48 +193,17 @@ gh run watch --repo <org>/dip-catalog
|
||||
> 유일한 수단이다(security-catalog 프로젝트에서 이식, 2026-08-03). 이 키가 없는 구버전
|
||||
> 리포트는 findings 총계 0건이면 보수적으로 실패 처리하는 예전 경로로 판정한다.
|
||||
|
||||
## 자체 빌드 (`.github/workflows/build-image.yml`)
|
||||
## 자체 빌드 축은 이 문서가 다루지 않는다
|
||||
|
||||
게이트 대응 우선순위(상위 태그 교체 → 베이스 OS 교체 → **자체 빌드** → 예외 승인)의 세 번째 레버를
|
||||
실행하는 워크플로다. 대상은 `images/<image>/` 에 빌드 정의가 있는 이미지이고(목록은 그 디렉토리가
|
||||
단일 출처), 실행기는 `scripts/build/build-hardened-image.sh` 하나다 — 빌드 → `verify.sh` → SBOM →
|
||||
`scan-sbom.sh` → `cve-gate.py` 를 순서대로 부른다(이 문서의 파이프라인을 그대로 재사용).
|
||||
신규 이미지 추가 절차·계약(`build.env`/`catalog.env`)은
|
||||
[.claude/image-authoring.md](../.claude/image-authoring.md).
|
||||
게이트가 상위 태그 교체·베이스 OS 교체로 해소되지 않는 차단 CVE 를 찾으면 자체 빌드로 간다.
|
||||
그 축의 단일 출처는 **[.claude/image-authoring.md](../.claude/image-authoring.md)** 다 —
|
||||
`build-image.yml` 의 트리거·게이트 강도·카탈로그 반영·레포 분리 계획이 전부 거기 있다.
|
||||
|
||||
> `sbom.yml` 과 별도 파일인 이유: `sbom.yml` 은 `vars.SBOM_PIPELINE_IMAGE` 컨테이너 안에서 도는데
|
||||
> 거기엔 docker/buildx 가 없다. 빌드는 호스트 러너여야 한다.
|
||||
이 문서가 알아야 할 것은 하나뿐이다: **자체 빌드 이미지도 카탈로그가 가리키는 한 위 스캔·게이트
|
||||
대상이다.** 실제로 `docker.io/paasup/*` 가 게이트 리포트에 등장한다.
|
||||
|
||||
| 트리거 | 대상 결정 | 빌드·검증·게이트 | 레지스트리 push | 카탈로그 태그 갱신 |
|
||||
|--------|----------|------------------|-----------------|-------------------|
|
||||
| `workflow_dispatch` | `image` 입력(필수) · `base_os`(비우면 `catalog.env` 의 `DEFAULT_BASE_OS`) · `push`(기본 `true`) | ✅ | `push=true` 일 때만 | 게이트 PASS + 태그 변경 시 |
|
||||
| `pull_request` (`images/**`) | 변경된 `images/<image>/` 를 diff 로 자동 탐지(복수면 매트릭스 병렬) | ✅ | ❌ | ❌ |
|
||||
|
||||
PR 트리거가 push 하지 않는 것은 `REGISTRY` 를 넘기지 않기 때문이다 — 태그가 `localhost/...` 로 남아
|
||||
push 를 시도할 수조차 없다(검증 전용 안전장치).
|
||||
|
||||
- **`schedule` 트리거는 없다.** 블라인드 정기 재빌드는 "정말 개선인지"를 매번 되묻게 만들어 제거했다.
|
||||
- **`sbom.yml` 의 게이트가 이 워크플로를 자동 호출하지 않는다.** 차단 CVE 를 찾아도 자체 빌드로 갈지는
|
||||
사람이 판단해 수동 실행한다 — 두 워크플로 사이에 자동 연결은 없다.
|
||||
- 레지스트리는 `REGISTRY_HOST: docker.io/paasup` 고정. 인증은 `DOCKERHUB_USER`/`DOCKERHUB_TOKEN`.
|
||||
|
||||
### 카탈로그 반영 — PR 은 자동 생성되지 않는다
|
||||
|
||||
게이트 PASS 이고 새 태그가 현재 카탈로그 태그와 다르면, 워크플로가 `catalog.env` 의 `CHART_DIRS` 아래
|
||||
`custom-values.yaml`/`dip-values.yaml` 을 `scripts/build/patch-catalog-tag.py` 로 갱신하고
|
||||
`build/<image>-<타임스탬프>` 브랜치를 push 한다. **여기까지가 자동이다.**
|
||||
|
||||
PR 오픈은 사람이 한다 — `GITHUB_TOKEN` 으로 PR 을 만드는 것 자체를 조직 정책이 막는다("Allow GitHub
|
||||
Actions to create and approve pull requests" 미허용, 리포 설정으로 변경 불가). 2026-08-04 실측으로
|
||||
확인했고(run 30882785612, GraphQL: `GitHub Actions is not permitted to create or approve pull requests`),
|
||||
`gh pr create` 호출은 워크플로에서 제거했다. 대신 Job Summary 에 compare 링크가 남는다.
|
||||
|
||||
병합 전에 사람이 해야 하는 것:
|
||||
|
||||
1. compare 링크로 PR 오픈.
|
||||
2. `gh workflow run helm-catalog-sbom --ref <브랜치>` 로 카탈로그 게이트 확인.
|
||||
3. **배포 검증** — 게이트 PASS 는 "동작한다"를 증명하지 않는다(스캐너는 런타임 요구사항을 보지 못한다).
|
||||
절차: [.claude/deploy-test-procedure.md](../.claude/deploy-test-procedure.md).
|
||||
> `build-image.yml` 이 `sbom.yml` 과 별도 파일인 이유: `sbom.yml` 은 `vars.SBOM_PIPELINE_IMAGE`
|
||||
> 컨테이너 안에서 도는데 거기엔 docker/buildx 가 없다. 빌드는 호스트 러너여야 한다.
|
||||
|
||||
## GitHub 설정 (워크플로 활성화에 필요)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user