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 никогда не должен попадать в репозиторий. Дальше соберём всё в боевой проект.

Проверьте себя
1. Что делает Ansible Vault?
AУскоряет выполнение playbook
BШифрует секреты (пароли, ключи), чтобы их можно было безопасно хранить в git и расшифровывать по паролю при запуске
CСоздаёт резервные копии серверов
DУправляет инвентарём
2. Что категорически нельзя коммитить в git при работе с Vault?
AЗашифрованный vault.yml
BФайл с паролем Vault (vault-password-file)
CОбычный playbook
Drequirements.yml