Существует несколько вариантов хранения паролей и других секретов, которые должна использовать программа Python, особенно программа, которая должна работать в фоновом режиме, когда она не может просто попросить пользователя ввести пароль.
Проблемы, которых следует избегать:
- Проверка пароля в системе контроля версий, где его могут увидеть другие разработчики или даже публика.
- Другие пользователи на том же сервере читают пароль из файла конфигурации или исходного кода.
- Наличие пароля в исходном файле, где другие могут видеть его через плечо, пока вы редактируете его.
Вариант 1: SSH
Это не всегда вариант, но, вероятно, лучший. Ваш закрытый ключ никогда не передается по сети, SSH просто выполняет математические вычисления, чтобы доказать, что у вас есть правильный ключ.
Чтобы это работало, вам нужно следующее:
- База данных или все, к чему вы обращаетесь, должно быть доступно по SSH. Попробуйте найти «SSH» плюс любой сервис, к которому вы обращаетесь. Например, "ssh postgresql" . Если это не функция в вашей базе данных, перейдите к следующей опции.
- Создайте учетную запись для запуска службы, которая будет выполнять вызовы в базу данных, и создайте ключ SSH .
- Либо добавьте открытый ключ к службе, которую вы собираетесь вызывать, либо создайте локальную учетную запись на этом сервере и установите открытый ключ там.
Вариант 2: переменные среды
Этот самый простой, так что это может быть хорошее место для начала. Это хорошо описано в приложении Twelve Factor . Основная идея заключается в том, что ваш исходный код просто извлекает пароль или другие секреты из переменных среды, а затем вы настраиваете эти переменные среды в каждой системе, в которой вы запускаете программу. Также может быть приятно, если вы используете значения по умолчанию, которые будут работать для большинства разработчиков. Вы должны сбалансировать это с тем, чтобы сделать ваше программное обеспечение «безопасным по умолчанию».
Вот пример, который извлекает сервер, имя пользователя и пароль из переменных среды.
import os
server = os.getenv('MY_APP_DB_SERVER', 'localhost')
user = os.getenv('MY_APP_DB_USER', 'myapp')
password = os.getenv('MY_APP_DB_PASSWORD', '')
db_connect(server, user, password)
Посмотрите, как установить переменные среды в вашей операционной системе, и подумайте о запуске службы под собственной учетной записью. Таким образом, у вас нет конфиденциальных данных в переменных среды, когда вы запускаете программы под своей учетной записью. Когда вы настраиваете эти переменные среды, будьте особенно внимательны, чтобы другие пользователи не могли их прочитать. Проверьте права доступа к файлу, например. Конечно, любой пользователь с правами root сможет их прочитать, но с этим ничего не поделаешь.
Вариант 3: файлы конфигурации
Это очень похоже на переменные среды, но вы читаете секреты из текстового файла. Я все еще нахожу переменные среды более гибкими для таких вещей, как инструменты развертывания и серверы непрерывной интеграции. Если вы решите использовать файл конфигурации, Python поддерживает несколько форматов в стандартной библиотеке, например JSON , INI , netrc и XML . Вы также можете найти внешние пакеты, такие как PyYAML и TOML . Лично я считаю JSON и YAML наиболее простым в использовании, а YAML позволяет комментировать.
Три вещи, которые следует учитывать при использовании файлов конфигурации:
- Где файл? Возможно расположение по умолчанию, например
~/.my_app
, и параметр командной строки для использования другого расположения.
- Убедитесь, что другие пользователи не могут прочитать файл.
- Очевидно, что не передавайте файл конфигурации в исходный код. Возможно, вы захотите зафиксировать шаблон, который пользователи могут скопировать в свой домашний каталог.
Вариант 4: модуль Python
Некоторые проекты просто помещают свои секреты прямо в модуль Python.
# settings.py
db_server = 'dbhost1'
db_user = 'my_app'
db_password = 'correcthorsebatterystaple'
Затем импортируйте этот модуль, чтобы получить значения.
# my_app.py
from settings import db_server, db_user, db_password
db_connect(db_server, db_user, db_password)
Один проект, который использует эту технику - Django . Очевидно, что вы не должны фиксировать settings.py
в управлении исходным кодом, хотя вам может потребоваться зафиксировать файл с именем settings_template.py
, который пользователи могут копировать и изменять.
Я вижу несколько проблем с этой техникой:
- Разработчики могут случайно передать файл в систему контроля версий. Добавление его к
.gitignore
снижает этот риск.
- Часть вашего кода не находится под контролем исходного кода. Если вы дисциплинированы и ввели здесь только строки и цифры, это не будет проблемой. Если вы начнете писать здесь классы фильтров журналирования, остановитесь!
Если ваш проект уже использует эту технику, легко перейти к переменным среды. Просто переместите все значения параметров в переменные среды и измените модуль Python для чтения из этих переменных среды.