Ansible 실전 · 시크릿(ansible-vault) · 이론
ansible-vault — 저장소에 넣어도 되는 시크릿
한 줄 요약
Vault 는 시크릿을 저장소 밖으로 빼는 도구가 아니라, 저장소 안에 암호문으로 두고 실행 시점에만 푸는 도구다.
왜 이게 필요했나
.env 를 .gitignore 에 넣었다고 안전해지지 않는다. 환경변수는 같은 호스트에서 /proc/PID/environ 으로 그대로 읽히고, 크래시 리포트와 CI 로그와 컨테이너 이미지 레이어에 실려 나간다. 그리고 더 중요한 질문이 남는다 — 시크릿이 새었을 때 몇 분 안에 그 키를 폐기하고 교체할 수 있는가? 대부분의 팀에서 답은 "모른다"이다. 어디에 몇 벌이 복사돼 있는지 모르기 때문이다.
Vault 는 이 문제의 절반을 푼다. 시크릿이 코드와 같은 저장소에 있으므로 어디에 몇 개가 있는지 셀 수 있고, 리뷰를 거치며, 히스토리가 남는다. 나머지 절반(자동 로테이션, 짧은 수명 자격증명)은 외부 시크릿 매니저의 영역이다.
어떻게 동작하나
Vault 는 AES256 대칭키 암호화다. 열쇠는 비밀번호 하나이고, 그 비밀번호는 파일이나 프롬프트로 전달한다.
| 명령 | 하는 일 |
| --- | --- |
| ansible-vault create | 새 암호화 파일 생성 |
| ansible-vault encrypt | 기존 평문 파일을 암호화 |
| ansible-vault view | 복호화해서 보여 주기만 |
| ansible-vault edit | 복호화 → 편집 → 재암호화 |
| ansible-vault rekey | 새 비밀번호로 다시 암호화 |
| ansible-vault encrypt_string | 값 하나만 암호화해 YAML 에 인라인으로 |
암호화된 파일의 첫 줄은 $ANSIBLE_VAULT;1.1;AES256 형태의 헤더다. 이 줄이 없으면 그 파일은 평문이다. 감사할 때 가장 먼저 보는 것이 이 헤더다.
encrypt_string 은 파일 전체가 아니라 값 하나만 암호화한다. 그러면 변수 파일의 나머지는 평문이라 diff 를 읽을 수 있고, 시크릿만 암호문으로 남는다. 실무에서는 이쪽이 더 자주 쓰인다.
--vault-id 는 여러 키를 라벨로 구분한다. prod@파일 처럼 쓰면 헤더에 라벨이 박히므로, 운영 키와 개발 키를 섞어 쓰다 사고 나는 것을 막는다.
시크릿을 다루는 태스크에는 반드시 no_log: true 를 붙인다. 그러지 않으면 애써 암호화한 값이 실행 로그에 평문으로 찍힌다. 로그 수집 시스템은 대개 애플리케이션보다 접근 권한이 넓다.
현장에서 만나는 모습
첫째, 비밀번호 파일의 위치. .vault_pass 를 저장소 안에 두면 자물쇠 옆에 열쇠를 붙여 놓은 것과 같다. 반드시 .gitignore 에 넣고 권한을 600 으로 둔다.
둘째, 폐기가 먼저다. 시크릿이 평문으로 커밋된 것을 발견했다면 순서는 폐기 → 영향 조사 → 히스토리 정리다. 히스토리 재작성부터 하는 것은 순서가 틀렸다 — 공개된 값은 이미 자동 스캐너가 수집했을 수 있고, 포크와 클론과 CI 캐시에 남는다. 히스토리 정리는 유출을 되돌리는 조치가 아니라 재발을 줄이는 위생 작업이다.
셋째, rekey 는 옛 키를 무효화한다. rekey 후에는 옛 비밀번호로 그 파일을 열 수 없다. 여러 사람이 쓰는 키라면 교체 시점을 조율해야 한다.
다음 실습에서 할 것
비밀번호 파일을 안전하게 만들고, 변수 파일을 통째로 암호화하고, 값 하나만 인라인으로 암호화한다. 플레이북에서 복호화된 값을 써서 권한 600 파일을 만들고, no_log 로 로그 유출을 막는다. rekey 와 vault-id 를 거쳐 마지막에는 저장소 전체를 감사한다.