images/·manifests/helm/·.claude/ 의 20개 파일이 doc/decisions·doc/analysis 등 **이 레포에 존재한 적 없는 경로 15종을 48곳에서** 인용하고 있었다. security-catalog 에서 포팅할 때 따라온 것인데, 그 레포는 개인 레포(github.com/wbsong111/security-catalog)라 팀 구성원은 접근조차 못 한다 — "security-catalog 에 있으나 이관되지 않았다" 는 안내가 아무 역할을 하지 못했다. 원문을 통째로 복사하지 않았다 ---------------------------- 원본 문서들이 서로를 근거로 인용한다. decisions/0001 하나만 봐도 analysis/cnpg-image-baseline.md · analysis/vendor-unassessed-data-sources.md 처럼 **인용 목록에 없던 또 다른 미이관 문서**를 가리킨다. 복사는 문제를 옮기는 것이지 없애는 게 아니다. 그리고 대부분은 애초에 dip-catalog 가 더 나은 것을 갖고 있다. 7곳에서 인용되던 analysis/sles-oval-measurement.md 는 원문 스스로 "이 문서는 결정하지 않는다. 재측정하면 갱신된다" 고 밝히는 스냅샷인데, dip-catalog 는 같은 측정을 CoverageProbe 로 매 스캔마다 자동으로 한다. 문서를 복사하는 것보다 게이트를 가리키는 것이 정확하다. 그래서 성격별로 나눴다 --------------------- 재측정으로 복원 안 되는 것 → doc/decisions/ 에 자립적 ADR 로 다시 씀 (4건) 이미 단일 출처가 있는 것 → 그쪽으로 인용 교체 (11종 경로) ADR 4건은 security-catalog 0001·0005·0006·0007 이 원본이고, 결론과 근거만 추려 dip-catalog 맥락으로 새로 썼다 — **레포 밖을 가리키는 링크가 0이다.** 번호는 이 레포에서 0001~0004 로 다시 붙였고 원본 대응은 각 문서와 README 에 적었다. 왜 안 가져온 것은 안 가져왔는지도 README 표에 남겼다. 인용 교체는 카테고리별로: analysis/*-cve.md, cnpg-image-vuln-comparison.md → 해당 ADR · images/<image>/README.md analysis/sles-oval-measurement.md → 게이트 CoverageProbe (doc/sbom-pipeline.md) cve-zero-pipeline.md, architecture/build-pipeline.md → doc/sbom-pipeline.md image-selection.md → .claude/image-authoring.md charts/*/deploy-test.md → scripts/deploy-test/*.sh + 절차 문서 찾은 오류 2건 ------------- - images/cloudnative-pg/source.build.env 가 인용한 decisions/0004-cloudnative-pg-operator-self-build.md 는 **번호 오기**다. 원본 0004 는 postgresql-chart-selection 이고 이 결정은 0005 다. - cnpg-cluster values.yaml·templates/database.yaml 이 인용한 doc/deploy-test-cnpg.md 는 **원본 레포에도 없다.** CREATE EXTENSION 함정 설명은 주석 자체에 이미 있어 인용만 뺐다. 검증 ---- 우리 파일의 깨진 doc/ 인용 0건 (전수 스캔) 새 문서·수정 문서의 로컬 링크 전부 실재 확인 helm template cnpg-cluster · etcd · cloudnative-pg 정상 렌더 남은 doc/health-checking.md(144곳)·doc/integration/*(2곳)은 업스트림 CRD·차트 안의 문자열로 우리가 쓴 인용이 아니다 — 건드리지 않았다. Closes #33 Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# 0001. cnpg-cluster 의 PostgreSQL 이미지를 SUSE BCI 자체 빌드로 한다
|
||||
|
||||
- 날짜: 2026-07-28 (결정) · 2026-08-03 (`docker.io/paasup` 로 재빌드)
|
||||
- 상태: 확정
|
||||
- 원본: security-catalog ADR 0001 — dip-catalog 맥락으로 다시 썼다([README](README.md) 참고)
|
||||
|
||||
## 결정
|
||||
|
||||
`manifests/helm/cnpg-cluster/1.0.0` 의 PostgreSQL 이미지를 SUSE BCI 15.7 기반 자체 빌드로
|
||||
한다. 현재 태그는 [custom-values.yaml](../../manifests/helm/cnpg-cluster/1.0.0/custom-values.yaml)
|
||||
의 `postgresql.imageName` 이 단일 출처이고, 빌드 정의는
|
||||
[images/cnpg-postgresql/](../../images/cnpg-postgresql/)(`suse.Dockerfile` + `suse.build.env`)다.
|
||||
|
||||
## 배경
|
||||
|
||||
이전 값 `ghcr.io/cloudnative-pg/postgresql:18.4-system-trixie` 에 두 문제가 있었다.
|
||||
|
||||
1. `system` 은 **업스트림에서 deprecated 된 타입**이다 (in-core barman phase out 예정)
|
||||
2. 실효 CRITICAL/HIGH **6/26**, 게이트 차단 **32건** (2026-07-28 실측)
|
||||
|
||||
후보 셋을 비교했다.
|
||||
|
||||
| | A `standard-trixie` | B ubuntu:24.04 자체 빌드 | **C SUSE BCI 15.7 자체 빌드** |
|
||||
| --- | --- | --- | --- |
|
||||
| 실효 고유 C/H | 23 | 0 | 0 |
|
||||
| 측정 가능성 | trivy 완전 | trivy 완전 | trivy 완전 |
|
||||
| 서명·attestation | ✅ | ❌ | ❌ |
|
||||
| 미조사 사각지대 | 0 | 18건 | 18건 |
|
||||
| 배포 검증 | — | failover 2초 | failover 3초 |
|
||||
| gid | `postgres` | ⚠️ `tape` 가 gid 26 선점 | `postgres` |
|
||||
|
||||
## 근거
|
||||
|
||||
- **A 의 차단 23건은 전부 수정 버전이 없다.** Debian 판정이 `unimportant` 9 / `no-dsa` 7 /
|
||||
`postponed` 3 / 미분류 4 로, 어떤 조치로도 해소되지 않는다. KEV 교집합은 0건이다.
|
||||
- **C 는 0건이고, 그 0건이 측정된 0건이다.** 결정 당시에는 "trivy 가 SLES 15.7 을 커버하지
|
||||
않으므로 직접 평가해야 한다" 고 봤는데 **그 전제가 틀렸다**(2026-07-29 재측정). 깨끗한
|
||||
이미지도 findings 0 이라 "0건" 과 "데이터 없음" 이 구분되지 않았던 것이 원인이다. 올바른
|
||||
검사는 양성 대조이고, dip-catalog 는 그것을 `CoverageProbe` 로 **매 스캔마다** 한다
|
||||
([doc/sbom-pipeline.md](../sbom-pipeline.md)).
|
||||
- **C 는 B 의 gid 위생 문제가 없다.** B 는 gid 26 이 `tape` 그룹에 선점되어 있다.
|
||||
- **C 는 배포 검증을 통과했다** — CNPG 오퍼레이터 통합, 롤링 전환, 데이터 보존, failover 3초.
|
||||
- **SUSE 공식 PostgreSQL 차트는 대안이 아니었다** — 확장이 `plpgsql` 하나뿐이다. C 는
|
||||
`pgaudit`·`pgvector`·contrib 를 포함한다.
|
||||
|
||||
## 받아들인 비용
|
||||
|
||||
- **업스트림 서명·provenance·SBOM attestation 을 잃는다.**
|
||||
- **재빌드 책임을 진다.** PostgreSQL 마이너 릴리스마다, 베이스 보안 업데이트마다. 후보 B 에서
|
||||
이미 실증됐다 — 빌드 후 하루도 안 되어 glibc 업데이트로 findings 38 → 46.
|
||||
- **업스트림이 테스트하지 않는 구성이다.** CNPG bake 매트릭스는 Debian 3종뿐이다.
|
||||
- **`pg-failover-slots` 확장이 없다.** PGDG zypp 저장소에 패키지가 없다.
|
||||
- **미조사 사각지대 18건.** SUSE 는 "미평가" 를 문서 부재로 표현하므로 **무엇이 미평가인지
|
||||
열거할 수 없다.** 이것은 어떤 도구를 쓰든 같다(이 이미지 기준 벤더 데이터가 언급하지 않는
|
||||
패키지 61개 / 176개). `0/0` 의 근거가 그만큼 불완전하다.
|
||||
|
||||
## 재검토 조건
|
||||
|
||||
- **A 의 차단 23건에 수정 버전이 도착하면** — 업스트림 이미지로 돌아가는 것이 유리해진다.
|
||||
게이트 리포트의 `status: fixed` 여부로 감지된다.
|
||||
- **사각지대 18건 조사 결과가 C 에 불리하면.**
|
||||
- **재빌드 부담이 실제로 문제가 되면** — 분기 1회 이상 재빌드가 필요해지는 경우.
|
||||
- **SUSE 가 BCI 기반 CNPG 호환 이미지를 직접 발행하면** — 자체 빌드가 불필요해진다.
|
||||
@@ -0,0 +1,72 @@
|
||||
# 0002. cloudnative-pg 오퍼레이터를 소스 컴파일 자체 빌드로 대체하고, 자체 빌드 오케스트레이션을 하나로 통일한다
|
||||
|
||||
- 날짜: 2026-07-30 (결정) · 2026-08-04 (`docker.io/paasup` 로 재빌드)
|
||||
- 상태: 확정
|
||||
- 원본: security-catalog ADR 0005 — dip-catalog 맥락으로 다시 썼다([README](README.md) 참고)
|
||||
|
||||
## 결정
|
||||
|
||||
`manifests/helm/cloudnative-pg/0.29.0` 의 오퍼레이터 이미지를 자체 빌드로 한다. 현재 태그는
|
||||
[custom-values.yaml](../../manifests/helm/cloudnative-pg/0.29.0/custom-values.yaml) 의
|
||||
`image.repository`/`image.tag` 가 단일 출처이고, 빌드 정의는
|
||||
[images/cloudnative-pg/](../../images/cloudnative-pg/)다 — 업스트림 `release-1.30` 브랜치의
|
||||
pinned commit 을 직접 `go build` 로 컴파일하고, 최종 런타임 베이스는 SUSE BCI(`bci-micro`)다.
|
||||
|
||||
**추가로, 이 작업에서 `scripts/build/build-hardened-image.sh` 를 일반화해 OS 패키지
|
||||
재설치형(`cnpg-postgresql`)과 소스 컴파일형(`cloudnative-pg`)이 오케스트레이션 스크립트
|
||||
하나를 공유하게 했다.** 자체 빌드 이미지가 늘어날 때마다 방법론이 갈라지지 않게 하기
|
||||
위함이다. 계약은 [.claude/image-authoring.md](../../.claude/image-authoring.md) 가 갖는다.
|
||||
|
||||
## 배경
|
||||
|
||||
업스트림 `cloudnative-pg:1.30.0` 이 게이트에서 실효 HIGH 3건으로 차단됐다 — `CVE-2026-39822`
|
||||
(stdlib), `CVE-2026-56852`(`golang.org/x/text`), `GHSA-hrxh-6v49-42gf`(grpc).
|
||||
|
||||
셋 다 Go 바이너리에 **정적 링크된 모듈 버전**이 원인이라 앞선 두 레버가 통하지 않는다.
|
||||
|
||||
- 상위 태그 교체 — 상위 태그가 없다(2026-07-30 확인, 최신 릴리스가 여전히 `v1.30.0`)
|
||||
- 베이스 OS 교체 — 배포 이미지 베이스가 distroless 라 OS 패키지가 사실상 0개다
|
||||
|
||||
자체 빌드만 유효한 대응이었다. 세 CVE 모두 업스트림 `release-1.30` 브랜치에 이미 백포트돼
|
||||
있어, Go 의존성을 직접 올릴 필요 없이 그 커밋을 그대로 컴파일하면 됐다.
|
||||
|
||||
## 근거
|
||||
|
||||
- **`release-1.30` HEAD 는 실측으로 확인된 안전한 픽업 지점이다.** `go.mod` 비교로 세 CVE 의
|
||||
수정 버전이 전부 포함됨을 확인했고(stdlib 1.26.5, x/text 0.39.0, grpc 1.82.1), 재스캔으로
|
||||
실효 C/H 0/0 을 확인했다.
|
||||
- **게이트 통과가 "동작함" 을 증명하지 않는다는 원칙이 실제로 작동했다.** 1차 빌드는 게이트를
|
||||
0/0 으로 통과했지만 배포 검증에서 `Cluster` 리컨실이 `invalid architecture: amd64` 로
|
||||
실패했다. 오퍼레이터가 자신의 가용 아키텍처를 `operator/manager_<arch>` **파일 존재**로
|
||||
판단하는데, 업스트림의 멀티아치 심볼릭 링크를 "부수 장치" 로 오판해 제거했기 때문이다.
|
||||
같은 바이너리를 `/manager` 와 `/operator/manager_amd64` 양쪽에 COPY 해 해결했다.
|
||||
- **베이스 OS 는 BCI 로 통일한다는 결정([0001](0001-cnpg-postgresql-image.md))이 이 이미지에도
|
||||
적용된다.** 최초 설계는 "업스트림과 최대한 동일하게" 를 따라 distroless 를 그대로 썼으나
|
||||
카탈로그 정책과 어긋나 `bci-micro` 로 교체했고, 교체 후에도 게이트·배포 검증 PASS 를
|
||||
유지하는 것을 확인했다.
|
||||
- **오케스트레이션 통일이 회귀를 만들지 않는 것을 확인했다** — 스크립트를 일반화한 직후 기존
|
||||
`cnpg-postgresql` 을 다시 빌드해 태그·게이트 결과가 동일함을 확인했다.
|
||||
|
||||
## 받아들인 비용
|
||||
|
||||
- **업스트림 서명·provenance·SBOM attestation 을 잃는다.** ADR [0001](0001-cnpg-postgresql-image.md)
|
||||
과 동일한 비용이다.
|
||||
- **`SOURCE_COMMIT` 갱신을 사람이 한다.** 자동 추적하지 않는다 — 다음 CVE 발생 시 그 시점의
|
||||
유지보수 브랜치 최신 커밋을 사람이 골라 `source.build.env` 를 고쳐 PR 을 여는 것 자체가
|
||||
트리거다.
|
||||
- **`release-1.30` 은 순수 패치 백포트가 아니다.** 기능 커밋 2개(`feat(pooler)` auth_user,
|
||||
`feat` check_empty_wal_archive)가 섞여 있다. 59 commits 전체를 라인 단위로 감사하지 않았고,
|
||||
배포 검증 스모크 수준으로만 회귀 여부를 봤다.
|
||||
- **업스트림이 테스트하지 않는 구성이다.** BCI 기반 오퍼레이터 빌드는 CNPG 의 CI 매트릭스에 없다.
|
||||
- **`bci-micro` 는 `bci-base` 와 달리 nonroot 계정이 없어 직접 만들어야 한다** — BCI
|
||||
micro/minimal 계열을 쓰는 다른 자체 빌드 이미지도 같은 작업이 필요하다.
|
||||
|
||||
## 재검토 조건
|
||||
|
||||
- **업스트림이 `v1.30.1` 이상을 정식 릴리스하면** — 상위 태그 교체가 다시 가능해지므로 자체
|
||||
빌드보다 우선한다.
|
||||
- **`release-1.30` 의 기능 커밋 2개가 실제 회귀를 일으키면** — 기능 커밋 이전 시점 등 다른
|
||||
pinned commit 으로 되돌린다.
|
||||
- **SUSE 가 CNPG 호환 공식 오퍼레이터 이미지를 발행하면** — 자체 빌드가 불필요해진다.
|
||||
- **`bci-micro` 에서 예기치 못한 런타임 문제(CA 신뢰 체인, TLS 등)가 나오면** — `bci-base` 로
|
||||
승격하거나 다른 BCI 변종을 재검토한다.
|
||||
@@ -0,0 +1,64 @@
|
||||
# 0003. etcd 배포 방식 — `groundhog2k/etcd` 단일 차트 채택, replicas=1(SPOF 수용)
|
||||
|
||||
- 날짜: 2026-07-31
|
||||
- 상태: 확정
|
||||
- 원본: security-catalog ADR 0006 — dip-catalog 맥락으로 다시 썼다([README](README.md) 참고)
|
||||
|
||||
## 결정
|
||||
|
||||
카탈로그의 etcd 배포 방식으로 `groundhog2k/etcd` 차트(오퍼레이터 없는 단일 StatefulSet
|
||||
차트)를 채택한다. 용도는 **단일 APISIX 인스턴스의 설정 저장소**이며, 쿼럼 HA 대신
|
||||
`replicas: 1` 로 배포한다 — **단일 장애점을 의도적으로 수용한다.** 기존 `bitnami/etcd` 기반
|
||||
배포는 이 차트로 교체한다.
|
||||
|
||||
카탈로그 위치는 [manifests/helm/etcd/1.1.12/](../../manifests/helm/etcd/1.1.12/)다.
|
||||
`replicas: 1` 은 `custom-values.yaml`(APISIX 용도), 쿼럼이 필요한 다른 소비자를 위한
|
||||
`replicas: 3` 프로파일은 `dip-values.yaml` 에 있다.
|
||||
|
||||
## 배경
|
||||
|
||||
dev 클러스터 `apisix` 네임스페이스에 이미 `data-apisix-etcd-0` PVC 가 있었다 — `bitnami/etcd`
|
||||
기반 APISIX 배포가 떠 있었다는 뜻이다. 이를 카탈로그 방식으로 정식 편입하며 이미지 출처를
|
||||
재검토했다. 후보는 `groundhog2k/etcd`(채택), `bitnami/etcd`(기존), `aenix-io/etcd-operator`
|
||||
류의 오퍼레이터 방식이다.
|
||||
|
||||
## 근거
|
||||
|
||||
**Bitnami 이미지 카탈로그 정책 변경(2025-08)이 결정적이었다.** `docker.io/bitnami/etcd` 는
|
||||
2025-08-28 부로 `bitnamilegacy/etcd` 로 이전되어 **동결**됐고(이후 보안 패치 없음),
|
||||
2025-09-29 공개 카탈로그 삭제 이후 신규 무료 티어는 44개 "development-only" 이미지로
|
||||
한정되며 그마저도 **버전 고정 없이 `latest` 태그만 제공**한다. 계속 패치를 받으려면 유료
|
||||
구독이 필요하다.
|
||||
|
||||
이는 카탈로그 목표와 두 지점에서 정면 충돌한다.
|
||||
|
||||
1. 패치가 멈춘 이미지는 시간이 지날수록 미수정 CVE 가 구조적으로 누적된다 —
|
||||
"CRITICAL/HIGH 0건" 을 유지 가능한 상태로 지속할 수 없다.
|
||||
2. 버전 고정 없는 `latest`-only 배포는 **롤링 태그 금지** 규칙과 애초에 양립하지 않는다
|
||||
([.claude/image-authoring.md](../../.claude/image-authoring.md)).
|
||||
|
||||
`groundhog2k/etcd` 는 업스트림 etcd 프로젝트의 원본 이미지(`quay.io/coreos/etcd`)를 그대로
|
||||
쓰므로 이 문제가 없다 — 다른 카탈로그 항목과 동일한 "업스트림 원본 이미지 + 버전 고정 태그"
|
||||
모델이다.
|
||||
|
||||
**오퍼레이터 방식은 측정 없이 정성적으로 배제했다.** 단일 APISIX 인스턴스에 쿼럼 HA 가
|
||||
불필요하다고 판단해, CRD·컨트롤러·RBAC 을 추가로 들이는 비용이 이득보다 크다고 봤다. 실측
|
||||
비교는 하지 않았다 — 이 판단은 근거가 정성적이라는 것을 명시해 둔다.
|
||||
|
||||
## 받아들인 비용
|
||||
|
||||
- **단일 장애점(SPOF)** — `replicas: 1` 이라 etcd Pod/노드 장애 시 APISIX 설정 조회·변경이
|
||||
즉시 불가능해진다. 쿼럼 기반 자동 복구가 없다.
|
||||
- **자동 백업이 없다** — 차트에 백업 기능이 없고, SPOF 상태에서 장애가 데이터 손실로 이어질
|
||||
수 있다. 스냅샷은 수동(`etcdctl snapshot save`)이다.
|
||||
- **Bitnami 가 기본 제공하던 부가 기능**(메트릭 익스포터 등 번들 구성)을 잃는다. 필요하면
|
||||
`serviceMonitor` 설정으로 별도 구성한다.
|
||||
- **쿼럼 HA 로 전환하려면 데이터 마이그레이션을 동반한 재배포가 필요하다** — `replicas` 는
|
||||
최초 배포 후 변경 불가다(차트 제약).
|
||||
|
||||
## 재검토 조건
|
||||
|
||||
- APISIX 를 다중 인스턴스로 확장해 etcd 쿼럼 HA 가 실제로 필요해지면.
|
||||
- etcd Pod 장애로 인한 SPOF 위험이 운영상 수용 불가능한 빈도로 발생하면.
|
||||
- `groundhog2k/etcd` 유지보수가 중단되거나, 이 결정의 근거였던 문제(패치 중단·롤링 태그
|
||||
강제)가 이 차트에서도 재현되면.
|
||||
@@ -0,0 +1,66 @@
|
||||
# 0004. etcd 이미지를 소스 컴파일 자체 빌드로 대체한다
|
||||
|
||||
- 날짜: 2026-07-31 (결정) · 2026-08-04 (`docker.io/paasup` 로 재빌드)
|
||||
- 상태: 확정
|
||||
- 원본: security-catalog ADR 0007 — dip-catalog 맥락으로 다시 썼다([README](README.md) 참고)
|
||||
|
||||
## 결정
|
||||
|
||||
[manifests/helm/etcd/1.1.12/](../../manifests/helm/etcd/1.1.12/) 의 이미지를 자체 빌드로
|
||||
한다. 현재 태그는 `custom-values.yaml` 의 `image.registry`/`image.repository`/`image.tag` 가
|
||||
단일 출처이고, 빌드 정의는 [images/etcd/](../../images/etcd/)다 — 업스트림 `v3.7.1` 태그가
|
||||
가리키는 commit 을 그대로 컴파일하되, `go.work` 워크스페이스 전역 `replace` 로
|
||||
`golang.org/x/text` 만 강제 업그레이드한다(버전은 `source.build.env` 의 `XTEXT_FIX_VERSION`).
|
||||
최종 런타임 베이스는 SUSE BCI(`bci-micro`) — [0002](0002-cloudnative-pg-operator-self-build.md)
|
||||
와 같은 패턴이다.
|
||||
|
||||
**추가로, 이 작업에서 `build-image.yml` CI 를 이미지 종류 무관하게 일반화했다**
|
||||
(`images/<image>/catalog.env` + `scripts/build/patch-catalog-tag.py`) — [0002](0002-cloudnative-pg-operator-self-build.md)
|
||||
의 백로그였다. 자체 빌드 이미지가 둘일 때는 하드코딩으로 버틸 수 있었지만 세 번째가 생기며
|
||||
실제로 한계에 부딪혔다.
|
||||
|
||||
## 배경
|
||||
|
||||
업스트림 `quay.io/coreos/etcd:v3.7.1` 이 게이트에서 실효 HIGH 1건으로 차단됐다 —
|
||||
`CVE-2026-56852`, `golang.org/x/text` 의 깨진 UTF-8 입력에 대한 `norm.Iter` 무한루프 DoS.
|
||||
|
||||
Go 바이너리에 정적 링크된 모듈 버전이 원인이라 베이스 OS 교체가 통하지 않고, 상위 태그도
|
||||
없다(2026-07-31 확인, 최신 릴리스가 여전히 `v3.7.1`). 게다가 [0002](0002-cloudnative-pg-operator-self-build.md)
|
||||
와 달리 **`release-3.7` 브랜치에 이 수정이 백포트조차 안 돼 있다**(브랜치 HEAD 가 태그와
|
||||
완전히 동일). 자체 빌드 외에는 즉시 대응할 방법이 없었다.
|
||||
|
||||
## 근거
|
||||
|
||||
- **워크스페이스 전역 `replace` 한 줄로 게이트가 PASS 로 바뀌는 것을 실측했다** — 실효 C/H
|
||||
0/1 → **0/0**. 이미 백포트된 커밋을 그대로 가져다 쓸 수 없었지만, 취약 모듈이 이 CVE
|
||||
하나뿐이라 직접 강제 업그레이드로도 충분했다.
|
||||
- **기능 검증(단일 노드 기동 + `etcdctl` put/get 왕복)이 통과했다.** 게이트 PASS 가 "동작함"
|
||||
을 증명하지 않으므로 `images/etcd/verify.sh` 로 확인한다. 최초 시도는 최종 베이스에 `sed`
|
||||
가 없어 실패했다(`sh: sed: command not found`) — `bci-base` 에는 있지만 `bci-micro` 에는
|
||||
없다는 것을 이때 처음 확인했다. 순수 셸 루프로 교체해 해결하고 그 제약을
|
||||
[.claude/image-authoring.md](../../.claude/image-authoring.md) 에 기록했다.
|
||||
- **CI 일반화가 기존 이미지에 회귀를 만들지 않는 것을 확인했다** — `catalog.env` 를 세
|
||||
이미지에 추가한 뒤 매트릭스로 동시에 검증 빌드했고 기존 두 이미지도 동일하게 PASS 했다.
|
||||
- **태그 치환 로직을 실제 카탈로그 파일 사본에 돌려 검증했다** — `imageName` 단일 필드
|
||||
(cnpg-cluster)와 `image:` 분리 필드(cloudnative-pg, etcd) 두 스타일 모두 기존 주석·포매팅을
|
||||
보존한 채 정확히 치환됨을 diff 로 확인했다.
|
||||
|
||||
## 받아들인 비용
|
||||
|
||||
- **업스트림 서명·provenance·SBOM attestation 을 잃는다.** [0001](0001-cnpg-postgresql-image.md)
|
||||
·[0002](0002-cloudnative-pg-operator-self-build.md) 와 동일한 비용이다.
|
||||
- **`SOURCE_COMMIT`·`XTEXT_FIX_VERSION` 갱신을 사람이 한다.** 자동 추적하지 않는다.
|
||||
- **매 patch 릴리스마다 이 자체 빌드를 다시 판단해야 한다** — 업스트림이 이 CVE 를
|
||||
`release-3.7` 에 백포트하기 전까지는 "이미 백포트된 안전한 픽업 지점" 이 없어 재검토 부담이
|
||||
[0002](0002-cloudnative-pg-operator-self-build.md) 보다 크다.
|
||||
- **업스트림이 테스트하지 않는 구성이다.** BCI 기반 etcd 빌드는 etcd 의 CI 매트릭스에 없다.
|
||||
- **강제 업그레이드가 `server`/`etcdctl`/`etcdutl` 각각에 반영됐는지는 SBOM 스캔으로만 간접
|
||||
확인했다** — `go version -m` 직접 대조는 하지 않았다.
|
||||
|
||||
## 재검토 조건
|
||||
|
||||
- **etcd 가 `release-3.7` 에 이 CVE 를 백포트하고 `v3.7.2` 이상을 릴리스하면** — 상위 태그
|
||||
교체가 다시 가능해지므로 자체 빌드보다 우선한다.
|
||||
- **`bci-micro` 에서 예기치 못한 런타임 문제가 나오면** — `bci-base` 로 승격하거나 다른 BCI
|
||||
변종을 재검토한다([0002](0002-cloudnative-pg-operator-self-build.md) 와 동일한 조건).
|
||||
- **다중 노드(쿼럼) 배포 검증에서 이 자체 빌드 이미지에 문제가 발견되면.**
|
||||
@@ -0,0 +1,47 @@
|
||||
# 결정 기록 (ADR)
|
||||
|
||||
카탈로그의 이미지·차트 선택 중 **재측정으로 복원되지 않는 것**만 여기 둔다.
|
||||
|
||||
CVE 건수·커버리지·패키지 버전 같은 수치는 게이트가 매 실행마다 다시 재므로 문서로 남기지
|
||||
않는다([doc/sbom-pipeline.md](../sbom-pipeline.md)). 반면 "왜 이 후보를 골랐고 무엇을 비용으로
|
||||
받아들였나" 는 어디에서도 재생성되지 않는다 — 그것이 ADR 의 범위다.
|
||||
|
||||
| # | 결정 | 날짜 | 상태 |
|
||||
|---|---|---|---|
|
||||
| [0001](0001-cnpg-postgresql-image.md) | cnpg-cluster 의 PostgreSQL 이미지를 SUSE BCI 자체 빌드로 한다 | 2026-07-28 | 확정 |
|
||||
| [0002](0002-cloudnative-pg-operator-self-build.md) | cloudnative-pg 오퍼레이터를 소스 컴파일 자체 빌드로 대체한다 | 2026-07-30 | 확정 |
|
||||
| [0003](0003-etcd-chart-selection.md) | etcd 는 `groundhog2k/etcd` 단일 차트 · replicas=1 로 배포한다 | 2026-07-31 | 확정 |
|
||||
| [0004](0004-etcd-image-self-build.md) | etcd 이미지를 소스 컴파일 자체 빌드로 대체한다 | 2026-07-31 | 확정 |
|
||||
|
||||
## 이 문서들의 출처
|
||||
|
||||
네 결정은 **security-catalog 프로젝트에서 내려졌고**, 그 레포의 ADR 0001·0005·0006·0007 이
|
||||
원본이다. dip-catalog 의 이미지·차트가 그 결정의 산물이므로 이 레포에도 근거가 있어야 한다.
|
||||
|
||||
**원문을 복사하지 않고 다시 썼다.** 원본은 같은 레포의 다른 문서(`doc/analysis/*`,
|
||||
`doc/plans/*`)를 근거로 인용하는데, 그것들까지 연쇄로 가져오면 dip-catalog 에 이중 기록이
|
||||
생기고 그러고도 링크가 또 밖으로 나간다. 그래서 **결론과 근거만 추려 자립적으로** 옮겼다 —
|
||||
이 디렉토리의 문서는 레포 밖을 가리키는 링크가 없다.
|
||||
|
||||
이관하지 않은 것과 그 이유. 아래 경로는 **security-catalog 안의 경로이고 이 레포에는 없다** —
|
||||
링크로 걸지 않은 이유가 그것이다.
|
||||
|
||||
| security-catalog 의 원본 | 왜 안 가져왔나 |
|
||||
|---|---|
|
||||
| `analysis/sles-oval-measurement.md` | 스캐너 커버리지 실측. 원문 스스로 "재측정하면 갱신된다" 고 밝히는 스냅샷이고, dip-catalog 는 이것을 `CoverageProbe` 로 **매 스캔마다 자동 재측정**한다 |
|
||||
| `analysis/*-cve.md` (3종) | 착수 시점의 CVE 스냅샷. 결론은 각 ADR 과 `images/<image>/README.md` 에 들어 있고, 현재 수치는 게이트가 낸다 |
|
||||
| `cve-zero-pipeline.md` · `architecture/build-pipeline.md` | [doc/sbom-pipeline.md](../sbom-pipeline.md) 와 [.claude/image-authoring.md](../../.claude/image-authoring.md) 가 dip-catalog 의 단일 출처다 |
|
||||
| `image-selection.md` | 이미지 선정 규칙은 [.claude/image-authoring.md](../../.claude/image-authoring.md) 가 갖는다 |
|
||||
| `charts/*/deploy-test.md` | 배포 검증은 `scripts/deploy-test/*.sh` 가 실행하고 절차는 [.claude/deploy-test-procedure.md](../../.claude/deploy-test-procedure.md) 가 갖는다. 기록은 실행 산출물이라 문서로 고정하지 않는다 |
|
||||
|
||||
## 새 ADR 을 언제 쓰나
|
||||
|
||||
- 이미지·차트 후보를 비교해 하나를 골랐고, **탈락한 후보가 있다**
|
||||
- 자체 빌드로 가면서 **업스트림 서명·provenance 를 잃는 비용을 받아들였다**
|
||||
- 기본값을 의도적으로 어겼다 (예: HA 대신 SPOF 수용)
|
||||
|
||||
반대로 "게이트가 차단해서 태그를 올렸다" 처럼 선택지가 하나뿐인 조치는 ADR 이 아니다 —
|
||||
커밋 메시지와 PR 설명이 기록이다([CLAUDE.md](../../CLAUDE.md) "작업 기록을 어디에 남기는가").
|
||||
|
||||
파일명은 `NNNN-<주제>.md`, 번호는 이어서 붙인다. 결정이 뒤집히면 문서를 지우지 않고 상태를
|
||||
`대체됨 → NNNN` 으로 바꾼다.
|
||||
Reference in New Issue
Block a user