GitHub Actions에서 시크릿 공유하기 — Vault 없이도 OK
작성자 Maxim Novak
Vaulted의 GitHub Action을 사용하면 HashiCorp Vault 없이도 GitHub Actions에서 시크릿을 공유할 수 있어. 인프라 없이 암호화된 자기파괴 링크를 만들어주는 액션이야. 클라이언트 사이드 AES-256-GCM 암호화를 사용하며, 단일 워크플로 스텝으로 동작해 — Secrets Manager 서버나 클라우드 설정이 전혀 필요 없어.
CI 파이프라인에서는 임시 자격증명이 항상 필요해. 단 한 번의 실행에만 존재해야 하는 배포 키, 마이그레이션 중에 두 저장소 간에 전달되는 토큰, 한 워크플로에서 교체하고 다른 워크플로에서 사용하는 자격증명.
"시크릿 매니저를 써라"는 게 표준 조언이야. 하지만 워크플로 간에 자격증명 하나를 넘기려고 HashiCorp Vault를 구축하거나 AWS Secrets Manager를 설정하는 건, 편지 한 통 부치려고 창고를 임대하는 것과 다름없어.
GitHub 저장소 시크릿은 정적인 경우에 잘 맞아 — 수명이 긴 API 키, 배포 토큰, 서비스 계정 자격증명. 하지만 임시적이거나 동적인 상황에는 부족해.
문제: CI/CD에서의 임시 시크릿 공유
저장소 시크릿은 변경 빈도가 낮고 단일 저장소에서 소비하는 값을 위해 설계됐어. 다음 시나리오는 커버하지 못해:
- 키 교체 중 일회성 인계 — 한 워크플로에서 자격증명을 교체하고, 다른 워크플로(또는 팀)가 새 값을 정확히 한 번만 가져가야 하는 경우.
- 저장소 간 자격증명 공유 — 두 저장소가 수명이 짧은 토큰을 교환해야 하는데, 어느 쪽도 영구 저장하면 안 되는 경우.
- 시간 제한 외부 인력 접근 — 계약자의 배포 기간이 끝나면 만료되어야 하는 CI 토큰.
- 시크릿이 언제 소비됐는지 파악 — 저장소 시크릿은 값이 읽혔는지, 언제 읽혔는지에 대한 가시성을 전혀 제공하지 않아.
이건 임시 문제야 — 임시 해결책이 필요해.
가벼운 접근법: 암호화된 자기파괴 링크
Vaulted GitHub Action을 사용하면 워크플로에서 직접 암호화된 자기파괴 시크릿을 만들고 가져올 수 있어 — 관리할 인프라가 없어.
시크릿 만들기:
- name: Share rotated credential
id: share
uses: vaulted-fyi/share-secret@v1
with:
secret: ${{ steps.rotate.outputs.new_token }}
views: 1
expires: 1h
이 스텝은 암호화된 시크릿을 담은 URL을 출력해. 암호화 키는 URL 프래그먼트 안에 있기 때문에 Vaulted 서버에 전달되지 않아.
시크릿 가져오기:
- name: Get shared credential
id: get
uses: vaulted-fyi/share-secret/get@v1
with:
url: ${{ needs.rotate.outputs.secret_url }}
- name: Deploy with rotated credential
run: ./deploy.sh
env:
API_TOKEN: ${{ steps.get.outputs.secret }}
가져오고 나면 링크는 소비되고 서버 측 암호문은 삭제돼. 시크릿은 해당 잡이 실행되는 동안에만 러너의 메모리에 존재해.
보안 모델
CI/CD 환경에서 안전하게 사용할 수 있는 세 가지 특성이 있어:
-
Zero-knowledge 암호화. 시크릿은 GitHub 러너 내부에서 AES-256-GCM으로 암호화된 후에야 프로세스를 떠나. 암호화 키는 URL 프래그먼트에 포함되어 있으며, 서버로 전송되지 않아. Vaulted는 자신이 복호화할 수 없는 암호문만 저장해. 이게 CI/CD에 적용된 클라이언트 사이드 암호화야.
-
자동 로그 마스킹. 이 액션은
core.setOutput전에core.setSecret을 호출해서, 시크릿 값의 모든 줄을 GitHub의 로그 마스커에 등록해. 여러 줄로 된 시크릿은 줄 단위로 마스킹되어, 부분 일치도 워크플로 로그에서 가려져. -
자기파괴 링크. 조회 제한과 시간 기반 만료는 서버 측에서 적용돼.
views: 1과expires: 1h로 만든 시크릿은 첫 번째 조회 또는 한 시간 후 — 둘 중 먼저 오는 시점에 — 영구 삭제돼.
시크릿 매니저 vs. 이 액션, 언제 뭘 써야 할까
| 시나리오 | 시크릿 매니저 | Vaulted Action |
|---|---|---|
| 수명이 긴 프로덕션 자격증명 | 적합 | 부적합 |
| 앱 런타임 설정 (DB URL, API 키) | 적합 | 부적합 |
| 워크플로 간 일회성 자격증명 인계 | 과도함 | 적합 |
| 임시 저장소 간 토큰 공유 | 과도함 | 적합 |
| 외부 인력 CI 접근 시간 제한 | 과도함 | 적합 |
| 교체 후 자격증명 배포 | 과도함 | 적합 |
시크릿 매니저는 애플리케이션이 런타임에 소비하는 시크릿에 적합한 도구야. Vaulted는 인계를 위한 것 — 자격증명이 한 곳에서 다른 곳으로 이동하며 유지되어서는 안 되는 그 순간을 위해서야.
시작하기
어떤 워크플로에든 이 액션을 추가하면 돼:
- uses: vaulted-fyi/share-secret@v1
with:
secret: ${{ secrets.TEMP_CREDENTIAL }}
views: 1
expires: 1h
GitHub Marketplace에서 찾을 수 있어. 이 액션으로 만든 시크릿은 웹 앱 및 CLI와 호환돼 — 어느 쪽에서 만들어도 다른 쪽에서 가져올 수 있어.
Vault 서버 없이. IAM 정책 없이. 인프라 없이. 자기파괴하는 암호화 링크만 있으면 돼.
관련 글
- API 키를 안전하게 공유하기 — API 자격증명을 위한 암호화된 자기파괴 링크
- .env 파일을 안전하게 공유하기 — Slack 없이 환경 설정 공유
- 엔드투엔드 암호화 설명 — 라이브 암호화 데모가 포함된 시각적 가이드