Ansible의 시크릿 마스킹
Ansible 플레이북은 서버에 연결하고 애플리케이션을 배포하기 위해 비밀번호와 API 토큰이 필요한 경우가 많습니다. 이러한 값은 작업 출력에도 나타날 수 있습니다. 예를 들어 명령이 비밀번호가 포함된 오류를 반환할 수 있습니다.
Ansible은 이 문제를 해결하는 데 도움이 되는 시크릿 마스킹 기능을 추가하고 있습니다. 출력에서 알려진 시크릿 값을 $REDACTED$로 바꾸고, 나머지 메시지는 읽을 수 있도록 유지합니다. 작업은 계속 원래 값을 사용합니다.
이 기능은 2026년 9월 10일에 병합된 Secret Masking API 풀 리퀘스트로 추가되었습니다. 이 글을 작성하는 시점에는 ansible-core 2.22 개발 빌드에서 사용할 수 있습니다. 아직 안정 버전에는 포함되지 않았습니다.
간단한 플레이북을 살펴본 다음, Semaphore UI에서 이 기능을 어떻게 활용할 계획인지 알아보겠습니다.
먼저 시크릿 등록하기
Ansible은 어떤 값을 마스킹해야 하는지 알아야 합니다. 새로운 API는 Vault로 암호화된 변수나 no_log로 표시된 모듈 매개변수처럼 알려진 시크릿 소스의 값을 등록합니다.
일반 변수에는 register_secret 필터를 사용할 수 있습니다. --extra-vars로 전달된 변수도 등록해야 합니다. 이름을 db_password로 지정하는 것만으로는 충분하지 않습니다.
이 예제에서는 가상의 데이터베이스 비밀번호를 사용합니다. masking.yml이라는 플레이북을 만드세요.
- name: Try secret masking
hosts: localhost
gather_facts: false
vars:
db_password: "example-db-password-123456"
tasks:
- name: Register the password before using it
ansible.builtin.set_fact:
db_password: "{{ db_password | ansible.builtin.register_secret }}"
- name: Show a message containing the password
ansible.builtin.debug:
msg: "Connecting to db.internal with password={{ db_password }}"
첫 번째 작업은 비밀번호를 등록합니다. 필터는 원래 값을 반환하므로 플레이북은 여전히 그 값으로 데이터베이스에 연결할 수 있습니다. 어떤 작업이든 해당 값을 출력하기 전에 등록을 완료해야 합니다.
ansible-core 2.22 개발 빌드로 플레이북을 실행하세요.
ansible-playbook -i localhost, -c local masking.yml
두 번째 작업은 다음 메시지를 표시합니다.
Connecting to db.internal with password=$REDACTED$
여기서는 마스킹을 보여 주기 위해서만 비밀번호를 출력합니다. 실제 플레이북에서는 시크릿 소스에서 비밀번호를 가져오고, 자격 증명을 의도적으로 출력하지 마세요.
Semaphore UI와의 통합
Semaphore UI는 사용자가 어떤 변수를 시크릿으로 표시했는지 이미 알고 있습니다. 향후 버전에서는 이 정보를 사용해 해당 값을 Ansible에 자동으로 등록할 계획입니다.
이를 위해 Ansible의 _SECRETS_INPUT_FILES 옵션을 사용할 예정입니다. 이 옵션은 _ANSIBLE_SECRETS_INPUT_FILES 환경 변수로 설정하며, Ansible이 플레이북 시작 전에 시크릿 목록을 읽을 수 있도록 합니다.
입력은 YAML 또는 JSON 형식으로 제공할 수 있습니다. 예제의 비밀번호가 포함된 문서는 다음과 같습니다.
version: 1
secrets:
- example-db-password-123456
이 목록은 Ansible에 무엇을 마스킹해야 하는지 알려 줍니다. 변수 자체는 여전히 플레이북에 별도로 전달됩니다.
계획 중인 통합은 다음 시크릿 값을 지원할 예정입니다.
- 변수 그룹(Variable Groups) — 작업에서 사용하도록 저장한 시크릿.
- 설문(Surveys) — 작업을 시작할 때 입력하는 시크릿 답변.
이러한 값에 대해서는 각 플레이북에 register_secret 작업을 추가할 필요가 없어집니다.
이 방식을 ansible-core 2.22 개발 빌드에서 테스트했습니다. 등록한 값은 debug 메시지, 명령 결과, 오류 메시지, 상세 출력, Ansible 로그 파일에서 마스킹되었습니다. 파이프로 목록을 전달하는 방식도 작동했으며, 별도의 시크릿 파일을 디스크에 쓰지 않아도 되었습니다.
이 옵션은 현재 내부용이며 변경될 수 있습니다. Semaphore UI 지원은 향후 릴리스에 계획되어 있으며, 호환되는 Ansible 버전이 필요합니다.
예제: 애플리케이션 배포하기
애플리케이션을 배포하는 작업 템플릿(Task Template)이 있다고 가정해 보겠습니다. 배포 스크립트는 변수 그룹에 시크릿으로 저장된 API 토큰을 사용합니다.
계획 중인 통합에서는 작업이 다음과 같이 진행됩니다.
- Semaphore UI가 토큰을 플레이북에 전달합니다.
- 실행 전에
_SECRETS_INPUT_FILES를 통해 Ansible의 마스킹 목록에도 토큰을 전달합니다. - 플레이북은 실제 토큰으로 배포 스크립트를 실행합니다.
- 스크립트가 출력에 토큰을 포함하면, Ansible은 표시되는 결과에서 해당 토큰을 마스킹합니다.
예를 들어 토큰이 만료되었다면 작업 로그에 다음 메시지가 나타날 수 있습니다.
Deployment rejected: service=payments environment=staging token=$REDACTED$ reason=token expired
로그를 읽는 모든 사람에게 토큰을 노출하지 않고도 어떤 배포가 왜 실패했는지 확인할 수 있습니다. 설문의 시크릿 필드로 입력한 임시 토큰에도 같은 흐름이 적용됩니다.
제한 사항
마스킹은 등록된 값에 적용됩니다. 개발 버전 구현에서는 4자 미만의 시크릿을 건너뛰며, 인코딩되거나 다른 방식으로 변환된 값은 별도로 등록해야 할 수 있습니다.
또한 프로세스 인수, 플레이북이 작성한 파일, Ansible 외부에서 생성된 로그의 자격 증명은 보호하지 않습니다. 출력 전체를 비공개로 유지해야 하는 작업에는 계속 no_log: true를 사용하세요.
이 통합으로 Semaphore UI에서 시크릿으로 표시한 값을 Ansible의 마스킹 시스템도 인식하게 됩니다. 이를 통해 작업 로그에 자격 증명이 남는 것을 줄이면서 문제 해결에 유용한 정보는 유지할 수 있습니다.

