자체 빌드 드리프트 스캔·재빌드 트리거를 제거하고 CI 파이프라인을 정리한다
hardened-containers가 이미 rescan.yml로 매일 자율 재스캔·재빌드하고, sbom.yml이 custom-values.yaml 기준으로 자체 빌드 이미지를 다른 카탈로그 이미지와 동일하게 스캔하고 있어 self-build-drift-check.yml의 트리거·전용 스캔이 순수 중복이었다 (SECURITY_IMAGES_DISPATCH_TOKEN도 등록된 적 없어 트리거 스텝은 항상 실패하던 죽은 코드). check-rebuild-needed.py가 더하던 fixable/no-fix 구분도 cve-gate.py 리포트에 이미 있어 흡수할 필요 없이 삭제했다. 근거는 ADR 0005. 곁들여 CI 위생 문제(trivy DB 캐시 없음, concurrency 없음, catalog-tag-update.yml의 브랜치 누적)를 함께 고치고, hardened-containers의 docs/image-authoring.md가 docs/image-authoring/ 로 분할된 것을 반영해 관련 링크를 정정했다. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ name: catalog-tag-update
|
||||
# 차트에 반영할지" 는 이 카탈로그가 판단한다(catalog/image-map/<image>.env).
|
||||
#
|
||||
# public raw URL 로 읽으므로 인증이 필요 없다. hardened-containers 쪽 시크릿·PAT 도 없다 —
|
||||
# 의존 방향은 카탈로그 → 이미지 단방향이다(docs/image-authoring.md "카탈로그 레포와의
|
||||
# 의존 방향은 카탈로그 → 이미지 단방향이다(docs/image-authoring/ci.md "카탈로그 레포와의
|
||||
# 계약", hardened-containers 레포).
|
||||
#
|
||||
# PR 은 자동 생성하지 않는다 — GitHub Actions 는 GITHUB_TOKEN 으로 PR 을 만들 수 없다는
|
||||
@@ -22,6 +22,12 @@ on:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: catalog-tag-update
|
||||
# push 도중 취소를 막는다 — 아래 고정 브랜치(build/catalog-tag-update)를 두고
|
||||
# 두 실행이 경합하는 것을 방지한다.
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
SECURITY_IMAGES_REPO: paasup/hardened-containers
|
||||
|
||||
@@ -51,10 +57,15 @@ jobs:
|
||||
if: steps.apply.outputs.count != '0'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
BRANCH="build/catalog-tag-update-$(date -u +%Y%m%d%H%M%S)"
|
||||
# 고정 브랜치명 하나를 재사용한다 — PR 은 사람이 열어야 해서(조직 정책) 매 실행
|
||||
# 새 브랜치를 만들면 방치된 동일 내용 브랜치가 날마다 쌓인다. 이 브랜치는 이
|
||||
# 워크플로만 쓰므로 force push 가 안전하다. 이미 이 브랜치로 PR 이 열려 있으면
|
||||
# force push 가 그 PR 을 갱신한다(원하는 동작) — PR 이 머지된 뒤면 다음 실행이
|
||||
# main 기준으로 새로 만든다.
|
||||
BRANCH="build/catalog-tag-update"
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git checkout -b "$BRANCH"
|
||||
git checkout -B "$BRANCH"
|
||||
|
||||
# apply-published-tags.py 가 이미 파일을 고쳤다 — 여기서는 그 결과를 커밋만 한다.
|
||||
FILES="$(python3 -c "
|
||||
@@ -74,7 +85,7 @@ jobs:
|
||||
-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"
|
||||
git push --force origin "HEAD:$BRANCH"
|
||||
|
||||
COMPARE_URL="https://github.com/${{ github.repository }}/compare/main...${BRANCH}?expand=1"
|
||||
{
|
||||
|
||||
@@ -32,6 +32,10 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: cve-edge-post
|
||||
cancel-in-progress: false # 외부로 POST 하는 잡이라 중간 취소보다 직렬화가 안전하다
|
||||
|
||||
jobs:
|
||||
cve-json:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -57,6 +61,20 @@ jobs:
|
||||
- name: git safe.directory
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
- name: 캐시 키 날짜 계산
|
||||
id: cache-date
|
||||
run: echo "date=$(date -u +%Y%m%d)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# trivy 취약점 DB 캐시. sbom.yml 과 같은 규칙 — 하루 단위 키, 실패해도 무시.
|
||||
- name: trivy DB 캐시
|
||||
continue-on-error: true
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ github.workspace }}/sbom-out/cache
|
||||
key: trivy-db-${{ steps.cache-date.outputs.date }}
|
||||
restore-keys: |
|
||||
trivy-db-
|
||||
|
||||
# 사설 레지스트리 인증: 시크릿으로 docker config.json 을 만들어 trivy 가 읽게 한다.
|
||||
- name: 레지스트리 인증 구성
|
||||
env:
|
||||
|
||||
@@ -26,6 +26,12 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: sbom-${{ github.ref }}
|
||||
# PR 증분 diff 는 base_ref...HEAD 기준이라 최신 실행이 이전 커밋들의 변경까지 모두
|
||||
# 포함한다 — 취소해도 누락이 없다. 스케줄 전체 스캔은 취소하지 않는다.
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
sbom:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -58,6 +64,24 @@ jobs:
|
||||
- name: git safe.directory
|
||||
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
|
||||
|
||||
- name: 캐시 키 날짜 계산
|
||||
id: cache-date
|
||||
run: echo "date=$(date -u +%Y%m%d)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# trivy 취약점 DB 캐시. 하루 단위 키라 같은 날 여러 번 돌아도 최초 1회만
|
||||
# 새로 받는다. DB 가 낡아도 trivy 가 스스로 갱신하므로 오래된 캐시(전날 키,
|
||||
# restore-keys 로 폴백)를 복원해도 정확성 문제는 없다 — 다운로드 분량만
|
||||
# 줄어든다. 캐시는 최적화이지 정확성 요건이 아니므로 실패해도 워크플로를
|
||||
# 막지 않는다.
|
||||
- name: trivy DB 캐시
|
||||
continue-on-error: true
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ github.workspace }}/sbom-out/cache
|
||||
key: trivy-db-${{ steps.cache-date.outputs.date }}
|
||||
restore-keys: |
|
||||
trivy-db-
|
||||
|
||||
# 사설 레지스트리 인증: 시크릿으로 docker config.json 을 만들어 trivy 가 읽게 한다.
|
||||
- name: 레지스트리 인증 구성
|
||||
env:
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
name: self-build-drift-check
|
||||
|
||||
# 배포 중인 자체 빌드 이미지(hardened-containers 레포가 만든 것)가 새 CVE 로 규정을 벗어났는지
|
||||
# 이 카탈로그가 스스로 스캔해 판정한다. "무엇이 배포 중인가"는 이 카탈로그만 안다 —
|
||||
# hardened-containers 는 자기 스스로 이 판단을 하지 않는다
|
||||
# (hardened-containers 레포 docs/image-authoring.md "재빌드는 이 레포가 스스로 트리거하지 않는다").
|
||||
#
|
||||
# 판정(scripts/build/check-rebuild-needed.py)이 재빌드 대상이라고 하면 hardened-containers 의
|
||||
# `build-image.yml` 을 `workflow_dispatch` 로 부른다. 그 워크플로가 실제 빌드·검증·게이트·
|
||||
# push·`published.json` 갱신을 한다 — 이 워크플로는 트리거만 한다.
|
||||
#
|
||||
# 레지스트리 push 와 카탈로그 반영은 이 워크플로가 하지 않는다. `catalog-tag-update.yml` 이
|
||||
# `published.json` 을 읽어가는 별도 경로로 반영한다.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 2 * * 1' # 매주 월요일 02:00 UTC
|
||||
|
||||
env:
|
||||
SECURITY_IMAGES_REPO: paasup/hardened-containers
|
||||
|
||||
jobs:
|
||||
drift-check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: trivy 설치
|
||||
run: |
|
||||
curl -fsSL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
|
||||
| sh -s -- -b /usr/local/bin
|
||||
trivy --version | head -1
|
||||
|
||||
- name: 배포 중인 자체 빌드 이미지 스캔
|
||||
id: scan
|
||||
run: |
|
||||
set -uo pipefail
|
||||
mkdir -p /tmp/drift-reports
|
||||
python3 scripts/build/check-rebuild-needed.py --list-refs > /tmp/refs.tsv
|
||||
while IFS=$'\t' read -r img ref fname; do
|
||||
[ -n "${fname:-}" ] || continue
|
||||
echo "스캔: $ref"
|
||||
trivy image --quiet --scanners vuln \
|
||||
--severity UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL \
|
||||
--format json "$ref" > "/tmp/drift-reports/$fname" \
|
||||
|| { echo "::warning::$img: 스캔 실패 ($ref) — 이 이미지는 판정에서 빠진다"
|
||||
rm -f "/tmp/drift-reports/$fname"; }
|
||||
done < /tmp/refs.tsv
|
||||
|
||||
python3 scripts/build/check-rebuild-needed.py \
|
||||
--reports /tmp/drift-reports \
|
||||
--summary-md /tmp/drift.md \
|
||||
--json-out /tmp/drift.json
|
||||
cat /tmp/drift.md >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
python3 - <<'PY' >> "$GITHUB_OUTPUT"
|
||||
import json
|
||||
rows = json.load(open("/tmp/drift.json"))
|
||||
print("images=" + json.dumps([r["image"] for r in rows if r["status"] == "rebuild"]))
|
||||
PY
|
||||
|
||||
- name: hardened-containers 재빌드 트리거
|
||||
if: steps.scan.outputs.images != '' && steps.scan.outputs.images != '[]'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.SECURITY_IMAGES_DISPATCH_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
[ -n "$GH_TOKEN" ] || { echo "::error::SECURITY_IMAGES_DISPATCH_TOKEN 시크릿 없음 — ${SECURITY_IMAGES_REPO} 에 workflow_dispatch 를 걸 권한이 있는 PAT 필요"; exit 1; }
|
||||
python3 -c "import json,sys; print('\n'.join(json.loads(sys.argv[1])))" '${{ steps.scan.outputs.images }}' | \
|
||||
while read -r img; do
|
||||
[ -n "$img" ] || continue
|
||||
echo "재빌드 트리거: $img"
|
||||
gh workflow run self-build-image --repo "$SECURITY_IMAGES_REPO" -f "image=$img"
|
||||
done
|
||||
{
|
||||
echo
|
||||
echo "재빌드를 트리거했다: ${{ steps.scan.outputs.images }}"
|
||||
echo "진행 상황: https://github.com/${SECURITY_IMAGES_REPO}/actions/workflows/self-build-image.yml"
|
||||
echo
|
||||
echo "게이트 PASS + push 성공 시 그 레포의 \`published.json\` 이 갱신되고,"
|
||||
echo "\`catalog-tag-update.yml\` 이 다음 실행에서 카탈로그에 반영한다."
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
Reference in New Issue
Block a user