# adc — 자체 빌드 adc(APISIX/API7 관리 CLI, apisix-ingress-controller 의 사이드카) 를 업스트림 소스에서 SUSE BCI 위에 직접 빌드한다. `manifests/helm/apisix/2.16.0/custom-values.yaml`의 `ingress-controller.deployment.adcContainer.image.repository`/`tag`가 이 산출물을 가리킨다. > **자체 빌드는 대응 우선순위 3번이다.** 상위 태그 교체·베이스 OS 교체로 목표를 > 만족할 수 있으면 그 쪽을 쓴다. 자체 빌드는 업스트림 서명·provenance·SBOM attestation 을 > 잃고 재빌드 책임을 지는 선택이다. ## 왜 자체 빌드하나 — "태그 교체로 끝난 줄 알았는데 아니었다" apisix 카탈로그 CVE 조치 중 `ghcr.io/api7/adc`를 0.27.1 → 0.29.0(확인 시점 최신 태그) 으로 올렸다. 업스트림 0.29.0 릴리스 노트: "distroless 이미지로 전환해 베이스 이미지 취약점을 0으로 줄였다" — 실제로 `trivy image` 원시 스캔은 CRITICAL/HIGH 0/0 이 맞다. **하지만 이건 벤더 등급만 본 결과다.** 카탈로그 게이트(`scripts/pipeline/cve-gate.py`) 는 `max(벤더, NVD)`로 재평가하는데, 이걸로 다시 돌리면 아래 4건이 실효 CRITICAL/HIGH 로 여전히 차단한다(2026-08-12 실측): | CVE | 실효 등급 | 벤더 | NVD | 패키지 | status | | --- | --- | --- | --- | --- | --- | | CVE-2019-1010022 | CRITICAL | LOW | CRITICAL (9.8) | libc6 | affected, 수정 없음 | | CVE-2019-1010023 | HIGH | LOW | HIGH (8.8) | libc6 | affected, 수정 없음 | | CVE-2018-20796 | HIGH | LOW | HIGH (7.5) | libc6 | affected, 수정 없음 | | CVE-2019-9192 | HIGH | LOW | HIGH (7.5) | libc6 | affected, 수정 없음 | 전부 2018~2019년 glibc regex/collating 스택오버플로 버그다. Debian 이 "affected, 수정 버전 없음"으로 영구 고정해뒀다 — `cnpg-postgresql` 자체 빌드 때 겪은 것과 완전히 같은 패턴("Debian 은 unimportant/no-dsa 로 판단해 안 고치는데 다른 배포판은 이미 백포트했음"). 이미 최신 태그(0.29.0)라 상위 태그 교체 레버는 소진됐고, 남은 건 베이스 OS 교체뿐이다. ## SUSE 로 바꾸면 실제로 해소되는지 사전 검증 `registry.suse.com/bci/bci-base:15.7` + `zypper install nodejs24`만으로 최소 이미지를 만들어 SBOM·스캔해봤다 — **위 4건이 전혀 안 잡힌다**(2026-08-12 실측). SUSE 글리브C 에는 이미 고쳐져 있다는 뜻이다. ## 업스트림과 다르게 하는 부분 — 딱 한 줄 업스트림 Dockerfile(`libs/tools/src/docker/Dockerfile`, 태그 `v0.29.0`)은 2단계다: ```dockerfile FROM node:lts-bookworm-slim AS builder # pnpm+nx 로 main.cjs 하나로 번들 ... FROM gcr.io/distroless/nodejs24-debian13:nonroot COPY --from=builder /build/dist/apps/cli/main.cjs . ENTRYPOINT [ "/nodejs/bin/node", "main.cjs" ] ``` 빌더 스테이지(pnpm/nx 빌드)는 정책 대상이 아니라(`.claude/image-authoring.md` 원칙 2) **업스트림 그대로 재사용한다.** 바뀌는 건 최종 스테이지 베이스 한 줄뿐이다: - `gcr.io/distroless/nodejs24-debian13:nonroot` → `registry.suse.com/bci/bci-base:15.7` + `zypper install nodejs24`(같은 Node 24 메이저 유지 — SUSE 표준 패키지라 cnpg-postgresql 때 겪은 openresty 전용 -devel 문제도 없다) - 엔트리포인트 경로 `/nodejs/bin/node` → `/usr/bin/node`(zypper 설치 경로, 실측) - non-root 사용자: distroless `:nonroot` 태그 대신 명시적으로 `adc` 시스템 계정 생성 애플리케이션 코드(`main.cjs` 번들)는 업스트림과 100% 동일하다 — apisix/ apisix-ingress-controller 자체 빌드보다 훨씬 단순한 유형(cnpg-postgresql 과 같은 "OS 패키지 재설치형"에 가깝다 — 소스를 여러 모듈 컴파일하는 게 아니라 빌더 스테이지를 그대로 두고 런타임 베이스만 바꾼다). 실측 빌드 시간도 2분 이내(대부분 pnpm install+nx build 시간). ## 소스·버전 관리 | 항목 | 값 | | --- | --- | | 소스 | `https://github.com/api7/adc.git` | | pinned commit | `source.build.env` 의 `SOURCE_COMMIT` — `v0.29.0` 태그(lightweight, peeled 커밋 없음)가 가리키는 실제 커밋 | | 빌더 | 업스트림과 동일한 `node:lts-bookworm-slim` — 정책 대상 아님(빌더 스테이지) | | 최종 베이스 | `registry.suse.com/bci/bci-base:15.7` + `nodejs24` | `SOURCE_COMMIT`은 **자동 추적하지 않는다.** 다른 자체 빌드 이미지와 동일하게, 사람이 업스트림 새 릴리스(또는 위 4건을 이미 해소한 버전)를 보고 `source.build.env`를 고쳐 PR을 여는 것 자체가 갱신 트리거다. **권장 점검 주기**: 카탈로그 게이트가 이 이미지의 차단 CVE를 다시 보고할 때, 또는 `api7/adc`가 다음 릴리스를 내놓았을 때 — 릴리스가 나오면 그쪽으로 갈아타는 것(대응 우선순위 a)이 이 자체 빌드를 유지하는 것보다 항상 우선이다. ## 빌드 ```sh # 로컬 빌드 (push 없음) IMAGE=adc BASE_OS=source bash scripts/build/build-hardened-image.sh /tmp/out # 레지스트리에 push 까지 IMAGE=adc BASE_OS=source REGISTRY=docker.io/paasup \ bash scripts/build/build-hardened-image.sh /tmp/out ``` 수행 순서: **빌드 → 기능 검증(`verify.sh`) → SBOM → 전 심각도 스캔 → 게이트 판정.** `verify.sh`는 non-root 실행 여부, `--version` 출력, `--help`의 커맨드 목록(dump/diff/ sync)을 확인한다 — **adc 는 실제 APISIX/API7 백엔드 접속이 필요한 명령이 대부분이라 그 연동 자체는 이 스모크 범위 밖**이다. dev 클러스터 배포 검증 (`.claude/deploy-test-procedure.md`)이 담당한다. **결과(2026-08-12 실측)**: 게이트 `PASS`, 커버리지 `ok`, 실효 CRITICAL/HIGH `0/0` (원본 4건에서 완전 해소). `docker.io/paasup/adc:0.29.0-security-hardened-20260812` 로 push 완료. ### 파일 구성 | 파일 | 역할 | | --- | --- | | `source.Dockerfile` | 빌드 정의 — 빌더 스테이지(업스트림 그대로) + SUSE BCI 최종 스테이지 | | `source.build.env` | pinned commit·버전(`BUILD_ARGS`에 나열한 이름만 `--build-arg` 로 전달됨) | | `verify.sh` | 기능 검증 — non-root·버전·--help 커맨드 확인 | 베이스 변종이 하나뿐이라 파일명이 `source.*` 로 고정돼 있다. ### 태그 ``` docker.io/paasup/adc:0.29.0-security-hardened-20260812 └ app ┘└ 슬러그 ┘└ 하드닝 ┘└ 빌드일 ┘ ``` ## 아직 안 한 것 — 배포 검증 게이트 PASS·기능 스모크테스트(버전+help)까지만 확인했다. **apisix-ingress-controller 와 함께 실제 APISIX/API7 백엔드에 접속해 dump/diff/sync 가 정상 동작하는지는 아직 확인하지 않았다** — `.claude/deploy-test-procedure.md` 절차로 카탈로그 반영 전 반드시 수행할 것(apisix-ingress-controller 자체 빌드는 이미 이 절차로 배포 검증 완료됨 — 같은 방식으로 진행).