Ansible Vault로 콘텐츠 암호화하기

Ansible Vault로 콘텐츠 암호화하기 (Encrypting content with Ansible Vault)

vault 비밀번호를 관리·저장하는 전략을 세웠다면 이제 본격적으로 콘텐츠를 암호화할 차례예요. Ansible Vault는 **변수(variables)**와 파일(files) 두 종류의 콘텐츠를 암호화할 수 있어요.

암호화된 콘텐츠에는 항상 !vault 태그가 붙어요. 이 태그는 Ansible과 YAML에게 해당 콘텐츠를 복호화해야 한다는 것을 알려주고, | 문자는 여러 줄 문자열을 허용하게 해 줘요. --vault-id로 만든 암호화 콘텐츠에는 vault ID 라벨도 함께 포함돼요.

출처: 문서

본문

암호화된 변수와 암호화된 파일의 주요 차이를 다음 표로 정리할게요.

암호화된 변수 (Encrypted variables) 암호화된 파일 (Encrypted files)
얼마나 암호화되나요? 평문 파일 안의 변수 파일 전체
언제 복호화되나요? 요청 시, 필요할 때만 로드되거나 참조될 때마다 [1]
무엇을 암호화할 수 있나요? 변수만 모든 구조화된 데이터 파일

[1] Ansible은 암호화된 파일에서 어떤 콘텐츠가 필요한지 파일을 복호화하기 전에는 알 수 없어요. 그래서 플레이북과 롤에서 참조되는 암호화된 파일은 전부 복호화해요.

Ansible Vault로 개별 변수 암호화하기

YAML 파일 안의 단일 값을 ansible-vault encrypt_string 명령으로 암호화할 수 있어요. vault 처리된 변수를 안전하게 보이게 유지하는 방법 하나는 "Keep vaulted variables safely visible"을 참고하세요.

변수 암호화의 장단점

변수 단위 암호화를 쓰면 파일이 여전히 쉽게 읽혀요. 플레이나 롤 안에서 인라인으로 평문 변수와 암호화 변수를 섞어 쓸 수 있죠. 하지만 비밀번호 교체(rotation)가 파일 단위 암호화만큼 간단하지 않아요. 암호화된 변수는 rekey할 수 없어요. 또한 변수 단위 암호화는 변수에만 동작해요. 작업(task)이나 다른 콘텐츠를 암호화하려면 파일 전체를 암호화해야 해요.

암호화된 변수 만들기

ansible-vault encrypt_string 명령은 여러분이 입력(또는 복사·생성)한 어떤 문자열이든 플레이북·롤·변수 파일에 넣을 수 있는 형식으로 암호화하고 포맷해 줘요. 기본 암호화 변수를 만들려면 encrypt_string 명령에 세 가지 옵션을 전달해요:

  • vault 비밀번호의 소스 (vault ID 유무와 상관없이 prompt, file, script)
  • 암호화할 문자열
  • 문자열 이름 (변수의 이름)

패턴은 이렇게 생겼어요:

ansible-vault encrypt_string <password_source> '<string_to_encrypt>' --name '<string_name_of_variable>'

예를 들어 a_password_file에 저장된 유일한 비밀번호로 문자열 foobar를 암호화하고 변수 이름을 the_secret으로 지정하려면:

ansible-vault encrypt_string --vault-password-file a_password_file 'foobar' --name 'the_secret'

위 명령은 다음 콘텐츠를 만들어요:

the_secret: !vault |
      $ANSIBLE_VAULT;1.1;AES256
      62313365396662343061393464336163383764373764613633653634306231386433626436623361
      6134333665353966363534333632666535333761666131620a663537646436643839616531643561
      63396265333966386166373632626539326166353965363262633030333630313338646335303630
      3438626666666137650a353638643435666633633964366338633066623234616432373231333331
      6564

dev vault ID 라벨과 함께 a_password_filedev 비밀번호로 문자열 foooodev를 암호화하고, 암호화된 변수 이름을 the_dev_secret으로 지정하려면:

ansible-vault encrypt_string --vault-id dev@a_password_file 'foooodev' --name 'the_dev_secret'

위 명령은 다음 콘텐츠를 만들어요:

the_dev_secret: !vault |
          $ANSIBLE_VAULT;1.2;AES256;dev
          30613233633461343837653833666333643061636561303338373661313838333565653635353162
          3263363434623733343538653462613064333634333464660a663633623939393439316636633863
          61636237636537333938306331383339353265363239643939666639386530626330633337633833
          6664656334373166630a363736393262666465663432613932613036303963343263623137386239
          6330

stdin에서 읽은 문자열 letmein을 암호화하고, a_password_filedev 비밀번호로 vault ID dev를 추가한 뒤 변수 이름을 db_password로 지정하려면:

echo -n 'letmein' | ansible-vault encrypt_string --vault-id dev@a_password_file --stdin-name 'db_password'

경고: 프롬프트 없이 시크릿 콘텐츠를 커맨드 라인에 직접 입력하면 그 시크릿 문자열이 쉘 히스토리에 남아요. 테스트 환경 밖에서는 이렇게 하지 마세요.

위 명령은 다음 출력을 만들어요:

Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a new line)
db_password: !vault |
          $ANSIBLE_VAULT;1.2;AES256;dev
          61323931353866666336306139373937316366366138656131323863373866376666353364373761
          3539633234313836346435323766306164626134376564330a373530313635343535343133316133
          36643666306434616266376434363239346433643238336464643566386135356334303736353136
          6565633133366366360a326566323363363936613664616364623437336130623133343530333739
          3039

암호화할 문자열을 프롬프트로 입력받으려면 a_password_filedev 비밀번호로 암호화하고, 변수 이름을 new_user_password로, vault ID 라벨을 dev로 지정하면 돼요:

ansible-vault encrypt_string --vault-id dev@a_password_file --stdin-name 'new_user_password'

위 명령은 다음 프롬프트를 띄워요:

Reading plaintext input from stdin. (ctrl-d to end input, twice if your content does not already have a new line)

암호화할 문자열(예: hunter2)을 입력하고 ctrl-d를 누르면 돼요.

경고: 문자열을 입력한 뒤 Enter를 누르지 마세요. 그러면 암호화된 값에 줄바꿈이 추가돼요.

위 과정은 다음 출력을 만들어요:

new_user_password: !vault |
          $ANSIBLE_VAULT;1.2;AES256;dev
          37636561366636643464376336303466613062633537323632306566653533383833366462366662
          6565353063303065303831323539656138653863353230620a653638643639333133306331336365
          62373737623337616130386137373461306535383538373162316263386165376131623631323434
          3866363862363335620a376466656164383032633338306162326639643635663936623939666238
          3161

위 예제들의 출력은 앞으로 재사용할 수 있게 어떤 플레이북·변수 파일·롤에든 추가할 수 있어요. 암호화된 변수는 평문 변수보다 크지만, 민감 콘텐츠를 보호하면서도 플레이북·변수 파일·롤의 나머지 부분은 평문으로 남겨 쉽게 읽을 수 있게 해 줘요.

암호화된 변수 보기

debug 모듈을 사용해 암호화된 변수의 원래 값을 볼 수 있어요. 변수를 암호화할 때 사용한 비밀번호를 반드시 전달해야 해요. 예를 들어 마지막 예제에서 만든 변수를 vars.yml이라는 파일에 저장했다면, 이렇게 복호화된 값을 볼 수 있어요:

ansible localhost -m ansible.builtin.debug -a var="new_user_password" -e "@vars.yml" --vault-id dev@a_password_file

localhost | SUCCESS => {
    "new_user_password": "hunter2"
}

Ansible Vault로 파일 암호화하기

Ansible Vault는 Ansible이 사용하는 모든 구조화된 데이터 파일을 암호화할 수 있어요. 다음을 포함하죠:

  • 인벤토리의 그룹 변수 파일
  • 인벤토리의 호스트 변수 파일
  • -e @file.yml 또는 -e @file.json으로 ansible-playbook에 전달하는 변수 파일
  • include_varsvars_files로 로드하는 변수 파일
  • 롤 안의 변수 파일
  • 롤 안의 defaults 파일
  • 작업(tasks) 파일
  • 핸들러(handlers) 파일
  • 바이너리 파일이나 그 외 임의의 파일

이 경우 파일 전체가 vault에 암호화돼요.

참고: Ansible Vault는 암호화된 파일을 만들거나 수정할 때 편집기를 사용해요. 편집기 보안에 대한 안내는 "Steps to secure your editor"를 참고하세요.

파일 암호화의 장단점

파일 단위 암호화는 사용하기 쉬워요. 암호화된 파일의 비밀번호 교체는 rekey 명령으로 간단하게 할 수 있어요. 파일 암호화는 민감한 값뿐 아니라 사용하는 변수의 이름까지 숨길 수 있어요. 하지만 파일 단위 암호화를 하면 파일의 내용을 쉽게 접근하고 읽을 수 없게 돼요. 특히 암호화된 작업 파일에서 문제가 될 수 있어요. 변수 파일을 암호화할 때는 "Keep vaulted variables safely visible"을 참고해 변수에 대한 참조를 암호화되지 않은 파일에 남겨 두는 방법을 쓸 수 있어요. Ansible은 로드되거나 참조될 때 암호화된 파일 전체를 항상 복호화해요. 왜냐하면 콘텐츠가 필요한지 알려면 복호화해야 하기 때문이에요.

암호화된 파일 만들기

multi_password_filetest 비밀번호로 foo.yml이라는 새 암호화 데이터 파일을 만들려면:

ansible-vault create --vault-id test@multi_password_file foo.yml

도구는 편집기($EDITOR로 정의된 편집기, 기본은 vi)를 실행해요. 콘텐츠를 추가하고 편집기 세션을 닫으면 파일이 암호화된 데이터로 저장돼요. 파일 헤더는 만드는 데 사용한 vault ID를 반영해요:

$ANSIBLE_VAULT;1.2;AES256;test

vault ID my_new_password를 할당하고 비밀번호를 프롬프트로 입력받아 새 암호화 데이터 파일을 만들려면:

ansible-vault create --vault-id my_new_password@prompt foo.yml

역시 편집기에서 파일에 콘텐츠를 추가하고 저장해요. 나중에 그 파일을 복호화하고 싶을 때 찾을 수 있도록, 프롬프트에서 만든 새 비밀번호를 꼭 저장해 두세요.

기존 파일 암호화하기

기존 파일을 암호화하려면 ansible-vault encrypt 명령을 사용해요. 이 명령은 여러 파일을 한 번에 처리할 수 있어요. 예를 들어:

ansible-vault encrypt foo.yml bar.yml baz.yml

project ID로 기존 파일을 암호화하고 비밀번호를 프롬프트로 받으려면:

ansible-vault encrypt --vault-id project@prompt foo.yml bar.yml baz.yml

암호화된 파일 보기

편집하지 않고 암호화된 파일의 내용을 보려면 ansible-vault view 명령을 사용해요:

ansible-vault view foo.yml bar.yml baz.yml

암호화된 파일 편집하기

암호화된 파일을 제자리에서 편집하려면 ansible-vault edit 명령을 사용해요. 이 명령은 파일을 임시 파일로 복호화하고, 편집을 허용한 뒤, 내용을 저장·재암호화하고 편집기를 닫을 때 임시 파일을 제거해요. 예를 들어:

ansible-vault edit foo.yml

vault2 비밀번호 파일로 암호화되고 pass2 vault ID가 할당된 파일을 편집하려면:

ansible-vault edit --vault-id pass2@vault2 foo.yml

암호화된 파일의 비밀번호 및/또는 vault ID 변경하기

암호화된 파일의 비밀번호를 변경하려면 rekey 명령을 사용해요:

ansible-vault rekey foo.yml bar.yml baz.yml

이 명령은 여러 데이터 파일을 한 번에 rekey할 수 있고, 원래 비밀번호와 새 비밀번호를 묻습니다. rekey된 파일에 다른 ID를 설정하려면 새 ID를 --new-vault-id로 전달해요. 예를 들어 ppold 파일의 preprod1 vault ID로 암호화된 파일 목록을 preprod2 vault ID로 rekey하고 새 비밀번호를 프롬프트로 받으려면:

ansible-vault rekey --vault-id preprod1@ppold --new-vault-id preprod2@prompt foo.yml bar.yml baz.yml

암호화된 파일 복호화하기

더 이상 암호화 상태로 유지하고 싶지 않은 암호화 파일이 있다면, ansible-vault decrypt 명령으로 영구히 복호화할 수 있어요. 이 명령은 파일을 암호화되지 않은 상태로 디스크에 저장하므로, 편집을 원하는 것인지 먼저 확인하세요.

ansible-vault decrypt foo.yml bar.yml baz.yml

암호화된 문자열 복호화하기

암호화된 문자열의 내용을 확인하고 싶다면 stdin으로 전달해 볼 수도 있어요:

echo -e '$ANSIBLE_VAULT;1.1;V2\neyJrZX...MTVx\nSU1JVDlJZlRrSXBkVThmLXhKS00xZGl6X3F3YXZmWWUteGJWaHNZZXZNWl9hMWZvLVRYM3ZUZDRvaHRR\nWkhIdkJmZEZWNlBwVjhNVjJFT05QbDFwandaazAiLCAiY2lwaGVydGV4dCI6ICJnQUFBQUFCblRjOU9u\nWmM2dDh2VEN5c3NTQVlyV0hMclNEOFZfSGd2eEVHdERCdkJfakFpcUpaWWNTV19sR2hPY0VsWEVweS0z\nQ0NBcmJfdUdsUEt0NzJuSmFxVVVmRFIzdz09In0=' | ansible-vault decrypt

대안으로 다음 명령을 쓰면 encrypt_string을 쓸 때처럼 Ansible이 입력을 요구하게 할 수 있어요(입력을 끝내려면 Ctrl+D를 두 번):

ansible-vault decrypt
Reading ciphertext input from stdin

편집기 보안 확보하기 (Steps to secure your editor)

Ansible Vault는 설정된 편집기에 의존하는데, 이 편집기가 비밀 노출의 원인이 될 수 있어요. 대부분의 편집기는 데이터 손실을 방지하는 방법이 있지만, 보통 시크릿의 평문 복사본을 담을 수 있는 추가 평문 파일에 의존해요. 편집기 문서를 참고해 보안 데이터를 노출하지 않도록 설정하세요. 다음 섹션은 흔한 편집기에 대한 몇 가지 안내이며, 완전한 편집기 보안 가이드로 받아들이면 안 돼요.

vim

명령 모드에서 다음 vim 옵션을 설정해 노출 사례를 피할 수 있어요. 특히 플러그인을 쓸 때 보안을 위해 수정해야 할 설정이 더 있을 수 있으니 vim 문서를 참고하세요.

  • 크래시나 중단 시 자동 저장처럼 동작하는 swapfile을 비활성화:
set noswapfile
  • 백업 파일 생성 비활성화:
set nobackup
set nowritebackup
  • viminfo 파일이 현재 세션에서 데이터를 복사하지 않도록 비활성화:
set viminfo=
  • 시스템 클립보드로의 복사 비활성화:
set clipboard=

이 설정들은 .vimrc에 둬서 모든 파일에 적용하거나, 특정 경로·확장자에만 적용할 수도 있어요. 상세 내용은 vim 매뉴얼을 참고하세요.

Emacs

다음 Emacs 옵션을 설정해 노출 사례를 피할 수 있어요. 특히 플러그인을 쓸 때 보안을 위해 수정해야 할 설정이 더 있을 수 있으니 Emacs 문서를 참고하세요.

  • 시스템 클립보드로 데이터를 복사하지 않기:
(setq x-select-enable-clipboard nil)
  • 백업 파일 생성 비활성화:
(setq make-backup-files nil)
  • 자동 저장 파일 비활성화:
(setq auto-save-default nil)

더 알아보기 (Learn more)

  • 변수 단위 암호화는 파일을 평문으로 유지하면서 민감 값만 보호하고 싶을 때, 파일 단위 암호화는 변수 이름까지 숨겨야 할 때 유용해요.
  • rekey 명령은 파일의 비밀번호·vault ID를 바꿀 때 써요. 암호화된 변수는 rekey할 수 없어요.
  • 편집기가 시크릿을 평문 파일로 남기지 않도록 설정해서 노출을 막으세요.