Ansible Vault: храним секреты безопасно
Урок 18 - храним пароли и ключи в git безопасно с помощью Ansible Vault.
«Пароль от базы в открытом виде в git - это утечка, которая ждёт своего часа. Vault шифрует секреты прямо в репозитории».
В playbook'ах неизбежно появляются секреты: пароли БД, API-ключи, приватные ключи. Хранить их открытым текстом в git - грубая ошибка безопасности. Ansible Vault шифрует секреты, так что в репозитории они лежат зашифрованными, а при выполнении расшифровываются по паролю.
Шифрование файла
# Создать новый зашифрованный файл с секретами
ansible-vault create group_vars/db/vault.yml
# Зашифровать существующий файл
ansible-vault encrypt secrets.yml
# Отредактировать (откроется в редакторе, расшифрованным)
ansible-vault edit group_vars/db/vault.yml
# Посмотреть содержимое
ansible-vault view group_vars/db/vault.yml
Зашифрованный файл в git выглядит как блок $ANSIBLE_VAULT;1.1;AES256 и нечитаемая каша - но Ansible при запуске расшифрует его по паролю.
Шифрование одной строки
# Зашифровать одно значение - удобно для отдельной переменной
ansible-vault encrypt_string 'SuperSecret123' --name 'db_password'
Результат можно вставить прямо в обычный YAML-файл переменных - так зашифрованным будет только секрет, а остальное останется читаемым.
Запуск с расшифровкой
# Спросить пароль интерактивно
ansible-playbook site.yml --ask-vault-pass
# Или взять пароль из файла (файл - вне git!)
ansible-playbook site.yml --vault-password-file ~/.vault_pass
Как работает под капотом
Vault использует симметричное шифрование AES256: один пароль и шифрует, и расшифровывает. При запуске playbook Ansible встречает зашифрованный блок, берёт пароль (из --ask-vault-pass или файла), расшифровывает содержимое в памяти и использует переменные как обычные - на диск расшифрованное не пишется. Это разделяет «код в git» и «секрет под паролем»: даже при утечке репозитория без пароля Vault секреты недоступны.
Смоделируем идею Vault симметричным шифром (учебный XOR + ключевой маркер). Это иллюстрация принципа, не настоящий AES.
# Учебная модель Vault: симметричное шифрование по паролю
def vault_cipher(text, password):
key = sum(ord(c) for c in password) % 256
return bytes((b ^ key) for b in text.encode())
secret = "db_password=SuperSecret123"
password = "myVaultPass"
encrypted = vault_cipher(secret, password) # шифруем
print("В git хранится (нечитаемо):", encrypted[:20], "...")
decrypted = vault_cipher(bytes(encrypted), password) # тот же пароль
print("Ansible расшифровал в памяти:", decrypted.decode())
wrong = vault_cipher(bytes(encrypted), "wrongPass") # неверный пароль
print("Без верного пароля - мусор:", wrong[:15])
Попробуй сам ▶ Тот же пароль расшифровывает текст обратно, а неверный даёт мусор. Реальный Vault использует стойкий AES256, но принцип «симметричный шифр по паролю» - тот же.
Частые ошибки
- Класть vault-пароль в git. Файл с паролем (
--vault-password-file) обязан быть вне репозитория и в.gitignore. - Шифровать весь файл с переменными. Часто удобнее
encrypt_stringдля отдельных секретов, оставляя остальное читаемым в diff'ах. - Один пароль на всё навсегда. Для разных окружений - разные vault-id, а пароли периодически ротировать.
Best practices
- Секреты - только в Vault; обычные переменные - в открытых файлах. Разделяй
vars.ymlиvault.yml. - Vault-пароль храни в менеджере секретов или CI, никогда не коммить.
- Используй
encrypt_stringдля точечных секретов - так diff остаётся осмысленным.
В реальной работе
Vault - рабочая лошадка для секретов, но у него есть нюансы эксплуатации. Полностью зашифрованный файл плохо читается в code review: ревьюер видит лишь изменившийся блок шифротекста, не понимая, что поменялось. Поэтому многие предпочитают encrypt_string - шифруют только сами значения секретов, оставляя структуру файла и имена переменных открытыми. Для разных окружений заводят разные vault-id со своими паролями, чтобы доступ к стейджу не давал доступа к продовым секретам. В больших организациях Vault часто дополняют или заменяют внешними хранилищами (HashiCorp Vault, облачные secret manager'ы) и подтягивают секреты через lookup-плагины в момент выполнения - тогда секреты вообще не лежат в репозитории, даже зашифрованными.
Итоги
Ansible Vault шифрует секреты симметрично по паролю: в git лежит зашифрованный текст, при запуске Ansible расшифровывает его в памяти. Пароль Vault никогда не должен попадать в репозиторий. Дальше соберём всё в боевой проект.