-
[GitHub Actions][공급망보안] 에어갭 환경에서 artifact attestation을 검증할 때 bundle, trusted roots, artifact 반입 순서를 어떤 체크리스트로 고정하나기타개발지식/풀스택개발 2026. 8. 20. 09:13
IT 리서치 노트
[GitHub Actions][공급망보안] 에어갭 환경에서 artifact attestation을 검증할 때 bundle, trusted roots, artifact 반입 순서를 어떤 체크리스트로 고정하나
GitHub artifact attestation을 이미 쓰고 있어도 에어갭 환경으로 넘어가면 검증 절차가 자주 무너진다. 2026년 8월 19일 기준 GitHub 공식 문서를 다시 보면, offline verification은 artifact 바이너리만으로 되는 작업이 아니라 attestation bundle, trusted_root.jsonl, GitHub CLI를 함께 반입한 뒤 실행하는 순서형 작업이다. 이 글은 에어갭 환경에서 artifact attestation을 검증할 때 bundle, trusted roots, artifact 반입 순서를 어떤 체크리스트로 고정해야 release gate와 감사 로그가 덜 꼬이는지 정리한다.
1. 개요
결론부터 말하면 에어갭 검증은
artifact → bundle → trusted root → CLI 실행순서를 강제하는 체크리스트가 있어야 한다. GitHub는 offline verify 가이드에서 bundle과 trusted_root.jsonl을 별도로 준비하라고 적고, offline environment에 가져올 입력물을 네 가지로 명시한다. artifact 파일만 옮겨서는 provenance 검증이 완성되지 않는다.즉 online 환경에서 attestation bundle을 내려받고 trusted root를 생성하는 단계와, offline 환경에서 artifact와 함께 검증하는 단계를 분리해 적어야 한다. 이 흐름을 반입 manifest로 고정하면 누락된 입력물 때문에 검증이 흔들리는 일을 크게 줄일 수 있다.
2. 어디서 실제로 막히는가
실무에서 가장 자주 생기는 막힘은 세 가지다. 첫째, artifact 바이너리만 에어갭 환경으로 옮기고 attestation bundle을 빼먹는다. 둘째, trusted_root.jsonl을 오래된 파일로 재사용해 현재 서명 material과 mismatch가 났는지 판단하지 못한다. 셋째, GitHub CLI 버전과 bundle 파일명, artifact 해시를 같은 manifest에 남기지 않아 다음 검증자가 입력물을 다시 찾아야 한다.
GitHub concept 문서는 artifact attestations가 workflow 링크, repository, environment, commit SHA까지 포함한 signed claims라고 설명한다. 그러므로 에어갭 검증은 '파일 무결성 하나'가 아니라 provenance bundle 전체를 독립적으로 들여오는 작업이다. offline verify 가이드도 먼저 bundle을 받고, 다음으로 trusted root를 받고, 마지막으로 offline 환경에 CLI, artifact, bundle, trusted root를 반입하라고 순서를 제시한다.
문제가 되는 순간은 release gate가 바쁠 때다. 온라인 환경에서는
gh attestation verify한 줄로 끝나던 작업이 에어갭에서는 입력물 네 종류와 두 환경을 가로지른다. 이때 artifact만 가져오거나 bundle만 가져오면 검증 실패 메시지가 provenance 정책 실패처럼 보여 원인 분리가 늦어진다. 사실은 policy가 틀린 게 아니라 입력물 반입 순서가 틀린 경우가 많다.- 증상: 에어갭 환경에서 verify 명령이 bundle 또는 trusted root 누락으로 실패한다.
- 오류: artifact만 있으면 provenance 검증도 가능하다고 오해한다.
- 실패: trusted_root.jsonl 생성 시각을 기록하지 않아 root freshness를 설명하지 못한다.
- 재발: 반입 manifest 없이 파일만 복사해 다음 검증자가 입력물을 다시 찾는다.
막히는 장면 실제 원인 먼저 확인할 값 offline verify가 안 된다 bundle 또는 trusted root 누락 반입 manifest와 파일명 provenance가 설명되지 않는다 bundle을 안 가져옴 download 단계 출력 파일명 키가 맞는지 불분명하다 trusted root freshness 미기록 trusted_root.jsonl 생성 시각 3. 실무에서 적용하는 순서
가장 실용적인 절차는 다섯 단계다. 1단계에서 online machine에서 attestation bundle을 다운로드한다. 2단계에서 같은 시점에 trusted_root.jsonl을 생성한다. 3단계에서 artifact, bundle, trusted root, GitHub CLI 버전을 반입 manifest에 적는다. 4단계에서 에어갭 환경에 네 입력물을 함께 옮긴다. 5단계에서
gh attestation verify --bundle --custom-trusted-root순서로 검증한다.- online machine에서 artifact bundle을 먼저 받는다.
- 동일 시점에 trusted_root.jsonl을 생성해 저장한다.
- artifact 이름, bundle 이름, trusted root 생성 시각을 manifest에 적는다.
- offline 환경에는 CLI까지 포함해 네 입력물을 함께 반입한다.
- verify 명령에서 bundle과 custom trusted root를 명시한다.
이 순서를 지키면 검증 실패를 두 단계로 자를 수 있다. 먼저 입력물 누락인지, 그다음 provenance 정책 실패인지다. 에어갭 환경에서 흔한 실패는 policy 평가 전에 파일 누락으로 끝나기 때문에, 반입 manifest를 만들지 않으면 같은 오류를 계속 '서명 문제'로 잘못 해석하게 된다.
또 GitHub 문서는 새 signed material을 offline environment로 가져올 때마다 trusted root를 새로 만드는 것이 best practice라고 적고 있다. 따라서 manifest에는 trusted_root.jsonl 생성 시각을 꼭 남기는 편이 좋다. 그래야 이후 root rotation이나 revoke 논의를 할 때 어떤 검증이 어떤 root freshness를 기준으로 이루어졌는지 설명할 수 있다.
4. 공식 문서와 예시 화면으로 확인하기
첫 공식 화면은 artifact attestation이 무엇을 증명하는지 보여 준다. GitHub는 attestation이 workflow 링크, repository, organization, environment, commit SHA 같은 provenance 정보를 담은 cryptographically signed claims라고 설명한다. 즉 에어갭 검증은 파일 무결성뿐 아니라 이 provenance 묶음을 제대로 반입했는지 확인하는 과정이다.
그래서 air-gap 반입 순서도 단순히 artifact 바이너리만 옮기는 것이 아니라, provenance bundle과 trusted root를 함께 가져오는 순서로 설계해야 한다.
두 번째 화면은 offline verify 가이드의 1단계다. GitHub는 먼저 online machine에서 attestation bundle을 받으라고 한다. 에어갭 환경 검증이 실패하는 가장 흔한 이유 중 하나는 artifact 파일만 옮기고 bundle을 안 옮기는 것이다.
이 시점부터 메모에는 artifact 해시와 bundle 파일명을 같이 남기는 편이 좋다. bundle 없이 들어온 artifact는 provenance 검증을 다시 온라인으로 되돌리게 만든다.
세 번째 자료는 trusted root 단계다. GitHub는 public repo는 Sigstore public good instance, private repo는 GitHub Sigstore instance를 사용하며, 둘 다 한 번에 받는 `gh attestation trusted-root` 명령을 제시한다. 이 단계가 빠지면 bundle이 있어도 offline verify를 재현하지 못한다.
또 문서는 새 signed material을 에어갭으로 들여올 때마다 trusted_root.jsonl을 새로 생성하는 것이 best practice라고 적고 있다. 오래된 trusted root 파일을 그대로 두면 root rotation이나 revoke 판단이 늦어질 수 있다.
네 번째 화면은 실제 반입 목록이다. GitHub는 offline environment에 GitHub CLI, artifact, bundle file, trusted root file을 가져오라고 명시한다. 순서가 없으면 사람은 대개 CLI와 artifact만 챙기고 bundle 또는 trusted root를 놓친다.
이 화면을 기준으로 반입 체크리스트를 고정하면 release gate가 훨씬 단단해진다. 검증 실패를 '키가 틀렸나?'로 시작하지 않고, 먼저 입력물 누락을 자를 수 있기 때문이다.
에어갭 검증은 입력물 순서를 구조화해 두는 것이 핵심이다. online 쪽에서 bundle과 trusted root를 만든 뒤, offline 쪽에서는 CLI와 artifact와 두 파일을 검증 manifest와 함께 읽는 순서가 있어야 한다.
이미 online 검증과 offline 검증을 나누는 글이 환경 분기를 설명했다면, 이번 표는 그 offline 분기를 실제 반입 체크리스트로 고정하는 후속편이다.
마지막 자료는 실제 명령 순서를 안전한 placeholder로 정리한 것이다. artifact, bundle, trusted root가 각각 어떤 이름으로 들어왔는지 적어 두면 에어갭 환경에서 뒤섞이지 않는다.
또 Docker image provenance와 attestation 글, multi-registry digest drift 글을 같이 보면 provenance evidence와 artifact 반입 검증을 같은 공급망 절차로 묶기 쉽다.
5. 주의사항과 리스크
첫 번째 리스크는 bundle 없이 artifact만 반입하는 것이다. 그러면 provenance 검증 자체가 불가능해지고, 팀은 서명이나 policy 문제처럼 더 큰 원인을 의심하게 된다. 두 번째는 trusted_root.jsonl을 너무 오래 재사용해 root freshness를 잃는 것이다. 세 번째는 GitHub CLI 버전과 입력물 이름을 기록하지 않아 다음 검증자가 재현하지 못하는 것이다.
에어갭 검증 문서에는 최소한 artifact 파일명, bundle 파일명, trusted root 생성 시각, CLI 버전, repository 식별자를 포함하는 편이 좋다. 이 다섯 값이 있으면 검증 실패를 provenance 내용과 입력물 누락으로 빨리 나눌 수 있다.
- artifact alone은 offline provenance 검증에 충분하지 않다.
- trusted_root.jsonl은 새 signed material 반입마다 갱신하는 편이 안전하다.
- 반입 manifest 없이 파일만 옮기면 감사와 재현이 모두 약해진다.
6. 결론
GitHub artifact attestation의 에어갭 검증은
artifact,bundle,trusted_root.jsonl,GitHub CLI네 입력물을 정해진 순서로 반입하는 작업이다. offline verify 명령 자체보다 먼저 입력물 누락을 없애는 체크리스트를 고정하면 release gate와 감사 로그가 훨씬 안정된다.- online 단계에서 bundle과 trusted root를 같이 만든다.
- offline 단계에는 네 입력물을 manifest와 함께 반입한다.
- verify 실패는 policy보다 먼저 입력물 누락인지 확인한다.
7. 참고 링크
'기타개발지식 > 풀스택개발' 카테고리의 다른 글