Практическое руководство по безопасному хранению секретов
### Практическое руководство по безопасному хранению секретов ## Введение При автоматизации управления конфигурациями с помощью Ansible часто возникает необходимость хранить чувствительные данные: п
Введение
При автоматизации управления конфигурациями с помощью Ansible часто возникает необходимость хранить чувствительные данные: пароли, ключи API, сертификаты, приватные ключи SSH. Хранить их в открытом виде в плейбуках или переменных – плохая практика, особенно если код хранится в системах контроля версий (Git) и доступен широкому кругу лиц.
Ansible Vault – встроенный инструмент Ansible, который позволяет шифровать файлы или отдельные строки так, что они становятся безопасными для хранения в репозитории. В этой статье мы рассмотрим практические сценарии использования Ansible Vault: от шифрования файлов до интеграции в CI/CD.
1. Основы Ansible Vault
Ansible Vault использует симметричное шифрование (AES256). Для работы с зашифрованными данными требуется пароль (или ключ), который необходимо вводить при каждом запуске плейбука.
1.1. Создание зашифрованного файла
Создадим файл secrets.yml, содержащий переменные с секретами:
ansible-vault create secrets.yml
Система запросит пароль (дважды) и откроет текстовый редактор (обычно vi). Введём содержимое:
db_password: SuperSecret123
api_key: 1a2b3c4d5e
После сохранения файл будет зашифрован. Попытка прочитать его обычным способом покажет бинарные данные.
1.2. Просмотр зашифрованного файла
Для просмотра содержимого без расшифровки на диск:
ansible-vault view secrets.yml
Будет запрошен пароль, после чего содержимое отобразится на экране.
1.3. Редактирование зашифрованного файла
ansible-vault edit secrets.yml
Команда расшифровывает файл во временный, открывает редактор, а после закрытия снова шифрует.
1.4. Расшифровка файла (не рекомендуется, если не требуется)
Если нужно временно убрать шифрование (например, для миграции):
ansible-vault decrypt secrets.yml
Внимание: после этого файл станет открытым текстом.
1.5. Смена пароля
ansible-vault rekey secrets.yml
Будет запрошен старый пароль, затем новый (дважды).
2. Использование зашифрованных данных в плейбуках
2.1. Прямое указание переменных
Самый простой способ – включить зашифрованный файл с переменными в плейбук:
- hosts: all
vars_files:
- secrets.yml
tasks:
- name: Use secret variable
debug:
msg: "Database password is {{ db_password }}"
При запуске плейбука Ansible запросит пароль vault:
ansible-playbook site.yml
2.2. Включение зашифрованных файлов внутри других файлов переменных
Можно включить зашифрованный файл в обычный YAML через !vault tag, но проще использовать vars_files.
2.3. Зашифрованные переменные в inventory
Иногда нужно зашифровать отдельные переменные в inventory (например, ansible_become_password). Для этого файл inventory (или отдельный файл переменных группы/хоста) можно зашифровать целиком.
3. Управление паролями vault
Ввод пароля вручную удобен для локальной работы, но при автоматизации (cron, CI/CD) требуется передавать пароль без интерактива.
3.1. Файл с паролем
Создайте файл, содержащий только пароль (одна строка). Например, .vault_pass.txt. Затем используйте опцию --vault-password-file:
bash
ansible-playbook site.yml --vault-password-file .vault_pass.txt
Никогда не сохраняйте файл с паролем в Git! Добавьте его в .gitignore.
3.2. Переменная окружения ANSIBLE_VAULT_PASSWORD_FILE
Установите переменную окружения, указывающую на файл с паролем:
export ANSIBLE_VAULT_PASSWORD_FILE=/path/to/.vault_pass.txt
ansible-playbook site.yml
Это избавляет от необходимости каждый раз указывать опцию.
3.3. Использование скриптов-исполнителей
Вместо статического файла можно указать исполняемый скрипт, который выводит пароль (например, из менеджера секретов HashiCorp Vault, lastpass, или просто echo). Скрипт должен возвращать пароль в stdout.
Пример простого скрипта get_vault_pass.sh:
#!/bin/sh
echo -n "my-secret-password"
Сделайте его исполняемым и используйте:
ansible-playbook site.yml --vault-password-file ./get_vault_pass.sh
Это удобно для интеграции с внешними системами.
4. Шифрование отдельных строк (encrypt_string)
Иногда нецелесообразно шифровать целый файл, если нужно скрыть лишь одно значение. Ansible Vault позволяет зашифровать отдельную строку и вставить её прямо в YAML-файл.
ansible-vault encrypt_string 'SuperSecret123' --name 'db_password'
Результат будет выглядеть так:
db_password: !vault |
$ANSIBLE_VAULT;1.1;AES256
666237313733363...
Такую строку можно вставить в любой YAML-файл. При использовании плейбука Ansible автоматически расшифрует её.
Также можно зашифровать строку для конкретного vault ID (см. раздел 5).
5. Работа с несколькими паролями (Vault IDs)
Начиная с Ansible 2.4 появилась возможность использовать несколько разных паролей для разных файлов или строк. Это полезно, если у вас есть разные окружения (dev, prod) и разные команды имеют доступ только к своим секретам.
При создании файла можно указать vault ID (метку):
ansible-vault create --vault-id dev@prompt secrets_dev.yml
Здесь dev – это идентификатор, @prompt означает, что пароль будет запрошен интерактивно. Можно указать файл: --vault-id prod@/path/to/prod.pass.
При запуске плейбука нужно указать все необходимые vault ID:
ansible-playbook site.yml --vault-id dev@.vault_pass_dev.txt --vault-id prod@.vault_pass_prod.txt
Ansible сам определит, какой пароль нужен для какого зашифрованного блока, по метке, сохранённой в зашифрованных данных.
Это особенно удобно, когда часть переменных зашифрована для разработчиков, а часть – только для админов продакшена.
6. Интеграция с CI/CD системами
В автоматических конвейерах (Jenkins, GitLab CI, GitHub Actions) нельзя вводить пароль вручную. Обычно используют один из подходов:
- Хранят пароль vault в секретах CI/CD-системы и передают его через переменную окружения, а затем записывают во временный файл или используют скрипт-обёртку.
- Используют внешние менеджеры секретов (HashiCorp Vault) и скрипт, который получает пароль оттуда.
- Для GitLab CI можно использовать переменную типа
VAULT_PASSи скрипт:
echo "$VAULT_PASS" > .vault_pass.txt
ansible-playbook playbook.yml --vault-password-file .vault_pass.txt
Важно: не выводите пароль в логах сборки.
7. Лучшие практики
7.1. Никогда не храните пароль от vault в репозитории
Добавьте в .gitignore все файлы, содержащие пароли (например, *.pass, .vault_pass.txt). Используйте скрипты или менеджеры паролей.
7.2. Ограничьте доступ к файлам с паролями
На серверах управления и в CI/CD убедитесь, что файлы с паролями доступны только нужным процессам и пользователям.
7.3. Регулярно меняйте пароли vault
Как и любые секреты, пароли vault должны периодически обновляться. Используйте ansible-vault rekey для смены пароля на всех зашифрованных файлах.
7.4. Шифруйте только чувствительные данные
Не шифруйте весь плейбук целиком – это затруднит ревью кода. Шифруйте отдельные файлы переменных или используйте encrypt_string.
7.5. Используйте vault ID для разделения окружений
Это позволит гибко управлять доступом к секретам.
7.6. Делайте резервные копии паролей
Потеря пароля vault сделает зашифрованные данные недоступными навсегда. Храните пароль в надёжном месте (менеджер паролей, физический сейф).
7.7. Проверяйте, что зашифровано
Команда ansible-vault view помогает быстро проверить содержимое. Также можно использовать grep на расшифрованном содержимом с осторожностью.
Заключение
Ansible Vault – мощный и простой инструмент для защиты конфиденциальных данных в ваших проектах Ansible. Его возможности покрывают большинство потребностей: от шифрования целых файлов до отдельных строк, поддержка нескольких паролей и интеграция с автоматизацией. Следуя лучшим практикам, вы обеспечите безопасность секретов и избежите их утечки.
Помните: безопасность начинается с правильного обращения с паролями. Никогда не храните их вместе с зашифрованными данными, используйте менеджеры секретов и регулярно обновляйте ключи.