Red Hat Certified Engineer (RHCE) #10 Ansible Vault: 비밀 관리

7 분 소요

#9 Tag와 조건부에서 작업을 선택적으로 실행하고 조건과 반복으로 흐름을 제어했습니다. 이번에는 플레이북이 다루는 비밀 값을 안전하게 보관하는 방법입니다. 데이터베이스 비밀번호, API 토큰, 사용자 초기 암호 같은 값을 평문으로 inventory나 변수 파일에 두면 git 저장소나 시험 채점 환경에 그대로 노출됩니다. Ansible은 이를 막기 위해 Ansible Vault라는 암호화 메커니즘을 제공합니다.

Vault는 변수 파일 전체 또는 단일 변수 하나를 AES256으로 암호화해 두고, 플레이북 실행 시점에만 비밀번호로 복호화해서 사용합니다. RHCE 시험에서는 “비밀 변수를 vault로 암호화하고 플레이북에서 사용하라”, “비번 파일을 두어 비대화식으로 실행되게 하라"가 단골 문제이므로, ansible-vault의 하위 명령과 실행 옵션을 손에 익혀 두겠습니다.

Vault가 푸는 문제 #

플레이북은 변수로 동작이 갈립니다. 그 변수 중에는 누구에게도 보여서는 안 되는 값이 섞여 있습니다.

  • 데이터베이스 접속 비밀번호
  • 외부 서비스의 API 키와 토큰
  • 사용자 계정의 초기 비밀번호
  • TLS 개인키 같은 인증 자료

이런 값을 group_vars/db/vars.yml에 평문으로 적어 두면 파일을 읽는 누구나 비밀을 알게 됩니다. Vault는 파일을 암호화된 상태로 디스크에 두고, 플레이북 실행 시 제공한 vault 비밀번호로만 복호화하므로, git에 커밋해도 내용이 드러나지 않습니다.

암호화된 파일은 첫 줄이 $ANSIBLE_VAULT;1.1;AES256으로 시작하고 그 아래로 16진수 덩어리가 이어집니다. Ansible은 변수 파일을 로드할 때 이 헤더를 보고 자동으로 복호화를 시도합니다.

ansible-vault 하위 명령 #

ansible-vault는 다음 하위 명령으로 암호화 파일을 다룹니다. 이 여섯 개가 시험에서 쓰는 전부입니다.

명령동작
ansible-vault create <파일>새 암호화 파일을 만들고 편집기로 연다
ansible-vault edit <파일>암호화 파일을 복호화해 편집기로 열고, 저장 시 다시 암호화한다
ansible-vault view <파일>암호화 파일의 내용을 화면에 복호화해 보여준다
ansible-vault encrypt <파일>기존 평문 파일을 암호화한다
ansible-vault decrypt <파일>암호화 파일을 평문으로 되돌린다
ansible-vault rekey <파일>vault 비밀번호를 새 비밀번호로 변경한다

create: 새 암호화 파일 만들기 #

처음부터 암호화된 변수 파일을 만들 때는 create를 씁니다. 비밀번호를 두 번 입력한 뒤 $EDITOR로 지정된 편집기가 열립니다.

암호화 파일 생성
ansible-vault create group_vars/db/secret.yml
# New Vault password:
# Confirm New Vault password:

편집기 안에서는 평범한 YAML로 작성합니다.

group_vars/db/secret.yml
# group_vars/db/secret.yml (편집기 안에서 보이는 평문)
db_root_password: "S3cr3t!root"
db_app_password: "App#2026pw"

저장하고 나오면 디스크에는 암호화된 형태로 기록됩니다.

암호화 상태 확인
cat group_vars/db/secret.yml
# $ANSIBLE_VAULT;1.1;AES256
# 39613266313764336239...

view와 edit: 보기와 수정 #

암호화 파일은 cat으로 보면 16진수만 나오므로, 내용 확인은 view로 합니다.

view로 내용 확인
ansible-vault view group_vars/db/secret.yml
# Vault password:
# db_root_password: "S3cr3t!root"
# db_app_password: "App#2026pw"

값을 고칠 때는 edit를 씁니다. 복호화한 임시 내용을 편집기로 열고, 저장하면 다시 암호화합니다.

edit로 수정
ansible-vault edit group_vars/db/secret.yml
# Vault password:

encrypt와 decrypt: 기존 파일 변환 #

이미 평문으로 작성해 둔 변수 파일이 있다면 encrypt로 한 번에 암호화합니다.

기존 파일 암호화
ansible-vault encrypt group_vars/web/secret.yml
# Vault password:
# Encryption successful

반대로 암호화를 풀어 평문으로 되돌릴 때는 decrypt를 씁니다.

평문으로 복호화
ansible-vault decrypt group_vars/web/secret.yml
# Vault password:
# Decryption successful

rekey: 비밀번호 변경 #

vault 비밀번호를 교체할 때는 rekey로 현재 비번을 입력한 뒤 새 비번을 설정합니다.

vault 비밀번호 변경
ansible-vault rekey group_vars/db/secret.yml
# Vault password:
# New Vault password:
# Confirm New Vault password:
# Rekey successful

변수 파일을 암호화해서 사용하기 #

실무와 시험의 표준 패턴은 그룹 변수를 둘로 나누는 방식입니다. 공개해도 되는 값은 vars.yml에, 비밀 값은 vault.yml에 둡니다.

group_vars 디렉터리 구조
group_vars/
  db/
    vars.yml      # 평문: db_user, db_port 등
    vault.yml     # 암호화: vault_db_password 등

암호화 파일 안에서는 변수 이름에 vault_ 접두사를 붙이는 관례가 흔합니다.

group_vars/db/vault.yml
# group_vars/db/vault.yml (ansible-vault edit로 본 평문)
vault_db_password: "S3cr3t!root"

평문 파일에서는 그 vault 변수를 일반 이름에 연결합니다. 이렇게 하면 플레이북은 평범한 변수명만 참조하고, 실제 비밀은 암호화 파일에만 존재합니다.

group_vars/db/vars.yml
# group_vars/db/vars.yml
db_user: appuser
db_port: 3306
db_password: "{{ vault_db_password }}"

플레이북에서는 평문 변수처럼 그대로 씁니다.

site.yml
# site.yml
- name: Configure database
  hosts: db
  tasks:
    - name: Set DB root password
      ansible.builtin.debug:
        msg: "connecting with {{ db_user }} / {{ db_password }}"

실행 시점에 vault 비밀번호를 제공해야 변수가 복호화됩니다.

vault 비밀번호 입력 실행
ansible-playbook site.yml --ask-vault-pass
# Vault password:

실행 시 비밀번호 제공 방법 #

암호화 변수를 쓰는 플레이북은 vault 비밀번호 없이는 실행되지 않습니다. 비번을 전달하는 방식은 두 가지입니다.

–ask-vault-pass: 대화식 입력 #

실행할 때 비밀번호를 직접 입력받습니다. 사람이 지켜보며 한 번 돌릴 때 적합합니다.

대화식 실행
ansible-playbook site.yml --ask-vault-pass

ansible-navigator로 실행할 때도 같은 옵션을 씁니다.

ansible-navigator 실행
ansible-navigator run site.yml -m stdout --ask-vault-pass

–vault-password-file: 비번 파일로 자동화 #

비밀번호를 파일에 한 줄로 적어 두고 그 파일 경로를 넘기면, 입력 없이 자동으로 복호화됩니다. cron이나 무인 실행, 그리고 시험에서 “비대화식으로 실행되게 하라"는 요구에 쓰는 방식입니다.

비번 파일로 비대화식 실행
echo 'mypassword' > ~/.vault_pass
chmod 600 ~/.vault_pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass

ansible.cfg에 등록해 두면 옵션 없이도 항상 그 파일을 쓰게 됩니다.

ansible.cfg
# ansible.cfg
[defaults]
vault_password_file = ~/.vault_pass

ansible-vault 하위 명령도 같은 옵션을 받으므로, 비번 파일이 있으면 viewedit도 비대화식으로 동작합니다.

비번 파일로 view 실행
ansible-vault view group_vars/db/vault.yml --vault-password-file ~/.vault_pass

encrypt_string: 단일 변수 인라인 암호화 #

변수 파일 전체가 아니라 한 값만 암호화하고 싶을 때는 encrypt_string을 씁니다. 출력으로 나온 암호문 블록을 평문 YAML 파일에 그대로 붙여 넣을 수 있습니다.

encrypt_string으로 암호화
ansible-vault encrypt_string 'S3cr3t!root' --name 'db_password'
# Vault password:
# db_password: !vault |
#           $ANSIBLE_VAULT;1.1;AES256
#           39613266313764336239...

이 출력을 평문 vars.yml에 붙여 넣으면, 파일 자체는 평문이지만 그 변수 하나만 암호화된 상태가 됩니다.

group_vars/db/vars.yml
# group_vars/db/vars.yml
db_user: appuser
db_password: !vault |
          $ANSIBLE_VAULT;1.1;AES256
          39613266313764336239...

비번을 표준 입력으로 받게 하면 파이프라인에서도 쓸 수 있습니다.

비대화식 encrypt_string
ansible-vault encrypt_string --vault-password-file ~/.vault_pass \
  'App#2026pw' --name 'db_app_password'

!vault 태그가 붙은 값은 Ansible이 변수를 평가할 때 자동으로 복호화하므로, 플레이북에서는 {{ db_password }}처럼 평범하게 참조합니다.

vault id: 비밀번호를 여러 개로 #

서로 다른 vault 비밀번호로 암호화한 파일을 한 플레이북에서 함께 쓸 때는 vault id로 레이블을 붙여 구분합니다. --vault-id 레이블@소스 형식으로 여러 개를 동시에 전달합니다.

vault id 여러 개로 실행
ansible-playbook site.yml \
  --vault-id dev@~/.vault_dev --vault-id prod@prompt

암호화할 때도 같은 레이블을 지정하면, 복호화 시 어떤 비번을 쓸지 Ansible이 레이블로 매칭합니다.

레이블 지정 암호화
ansible-vault encrypt --vault-id prod@~/.vault_prod group_vars/db/vault.yml

시험 포인트 #

  • 비번 파일 권한. --vault-password-file로 쓸 파일은 평문 비밀번호를 담으므로 chmod 600으로 본인만 읽도록 잠가 둡니다. 권한이 느슨하면 비밀 노출 위험이 그대로 남습니다.
  • –vault-password-file로 비대화식 실행. 시험에서 “비밀번호 입력 없이 실행되게 하라"가 나오면 비번 파일을 만들고 ansible.cfgvault_password_file에 등록하거나 옵션으로 넘깁니다. --ask-vault-pass는 대화식이라 자동화 요구에는 맞지 않습니다.
  • 암호화 대상 분리. 비밀은 vault.yml에, 평문은 vars.yml에 두고 평문에서 vault_ 변수를 참조하는 구조가 표준입니다. 채점 시 비밀이 평문으로 남아 있으면 감점입니다.
  • 단일 값은 encrypt_string. 파일 전체를 암호화하지 말라거나 한 변수만 가리라는 요구에는 encrypt_string 출력을 평문 파일에 인라인으로 붙입니다.
  • plays에 vault 변수가 있으면 비번 없이는 실패. ansible-vault view로 내용을 먼저 확인하고, 실행 옵션에 비번 제공이 빠지지 않았는지 점검합니다.

정리 #

이번 글에서 잡은 것:

  • Ansible Vault는 변수 파일이나 단일 변수를 AES256으로 암호화해 디스크에 안전하게 보관합니다.
  • 하위 명령. create,edit,view,encrypt,decrypt,rekey로 암호화 파일을 다룹니다.
  • 표준 패턴. group_vars/<그룹>/vault.yml에 비밀을 담고 평문 vars.yml에서 vault_ 변수를 참조합니다.
  • 실행 시 비번 제공. --ask-vault-pass는 대화식, --vault-password-file은 비대화식 자동화용이며 ansible.cfg에도 등록할 수 있습니다.
  • encrypt_string으로 단일 값을 인라인 암호화하고, --vault-id로 여러 비밀번호를 레이블로 구분합니다.

다음: Role 작성과 사용 #

비밀까지 안전하게 다루는 법을 잡았습니다. 이제 플레이북을 재사용 가능한 단위로 묶는 role로 넘어갑니다.

#11 Role 작성과 사용에서는 role의 디렉터리 구조(tasks/handlers/templates/vars/defaults), ansible-galaxy init로 골격을 만드는 법, 플레이북에서 role을 호출하는 방식, 그리고 시험에서 자주 나오는 “주어진 요구사항대로 role을 작성하고 적용하라” 유형까지 직접 만들어 보며 정리하겠습니다.

X