Как я могу безопасно сохранять секретные ключи и пароль в моей системе управления версиями?

Я сохраняю важные настройки, такие как имена хостов и порты серверов разработки и производства в моей системе управления версиями. Но я знаю, что это плохая практика хранить секреты (например, личные ключи и пароли базы данных) в репозитории VCS.

Но пароли - как и любые другие настройки - кажутся, что они должны быть версиями. Итак, каков правильный способ контроля версий паролей?

Я предполагаю, что это связано с сохранением секретов в их собственном файле настроек секретов и с зашифрованным файлом и контролем версий. Но какие технологии? И как это сделать правильно? Есть ли лучший способ сделать это?


Я задаю вопрос в целом, но в моем конкретном экземпляре я хотел бы хранить секретные ключи и пароли для сайта Django/Python с помощью git и github.

Кроме того, идеальное решение будет делать что-то волшебное, когда я нажимаю/тяну с помощью git - например, если файл зашифрованных паролей изменяется, выполняется script, который запрашивает пароль и расшифровывает его на месте.


EDIT: Для ясности я спрашиваю, где хранить секреты производства.

Ответ 1

Спрашивая этот вопрос, я решил использовать решение, которое я использую при разработке небольшого приложения с небольшой командой людей.

git-crypt

git -crypt использует GPG для прозрачного шифрования файлов, когда их имена соответствуют определенным шаблонам. Для intance, если вы добавили в свой файл .gitattributes...

*.secret.* filter=git-crypt diff=git-crypt

... тогда файл типа config.secret.json всегда будет перенаправлен на удаленные репозитории с помощью шифрования, но останется незашифрованным в локальной файловой системе.

Если я хочу добавить к вашему репо новый ключ GPG (человек), который может расшифровать защищенные файлы, запустите git-crypt add-gpg-user <gpg_user_key>. Это создает новую фиксацию. Новый пользователь сможет расшифровать последующие коммиты.

Ответ 2

Вы совершенно правы, чтобы зашифровать свой файл конфиденциальных настроек, сохраняя при этом файл в контроле версий. Как вы упомянули, лучшим решением будет тот, в котором Git будет прозрачно шифровать некоторые чувствительные файлы, когда вы нажимаете их так, чтобы локально (то есть на любом компьютере с вашим сертификатом) вы могли использовать файл настроек, но Git или Dropbox или тот, кто хранит ваши файлы в VC, не имеет возможности читать информацию в открытом тексте.

Учебное пособие по прозрачному шифрованию/расшифровке во время Push/Pull

Этот gist https://gist.github.com/873637 показывает учебник о том, как использовать Git smudge/clean filter driver с помощью openssl для прозрачного шифрования файлов с нажатой, Вам просто нужно выполнить начальную настройку.

Краткое описание того, как это работает

В основном вы создаете папку .gitencrypt, содержащую 3 bash скрипта,

clean_filter_openssl 
smudge_filter_openssl 
diff_filter_openssl 

которые используются Git для дешифрования, шифрования и поддержки Git diff. В этих сценариях определяется основная кодовая фраза и соль (исправлена!), И вы ДОЛЖНЫ гарантировать, что .gitencrypt никогда не нажимается. Пример clean_filter_openssl script:

#!/bin/bash

SALT_FIXED=<your-salt> # 24 or less hex characters
PASS_FIXED=<your-passphrase>

openssl enc -base64 -aes-256-ecb -S $SALT_FIXED -k $PASS_FIXED

Аналогичен для smudge_filter_open_ssl и diff_filter_oepnssl. См. Gist.

В вашем репо с конфиденциальной информацией должен быть файл .gitattribute(незашифрованный и включен в репо), который ссылается на каталог .gitencrypt(который содержит все Git, должен прозрачно шифровать/расшифровывать проект) и который присутствует на вашем локальном машина.

.gitattribute Содержание:

* filter=openssl diff=openssl
[merge]
    renormalize = true

Наконец, вам также необходимо добавить следующий файл в ваш .git/config файл

[filter "openssl"]
    smudge = ~/.gitencrypt/smudge_filter_openssl
    clean = ~/.gitencrypt/clean_filter_openssl
[diff "openssl"]
    textconv = ~/.gitencrypt/diff_filter_openssl

Теперь, когда вы нажимаете репозиторий, содержащий вашу конфиденциальную информацию, в удаленный репозиторий, файлы будут прозрачно шифроваться. Когда вы вытаскиваете с локального компьютера, который имеет каталог .gitencrypt(содержащий вашу кодовую фразу), файлы будут прозрачно дешифрованы.

Примечания

Я должен отметить, что в этом учебном пособии не описывается способ шифрования вашего файла настроек. Это будет прозрачно шифровать весь репозиторий, который будет перенаправлен на удаленный хост VC и расшифровать весь репозиторий, чтобы он был полностью расшифрован локально. Чтобы добиться желаемого поведения, вы можете разместить чувствительные файлы для одного или нескольких проектов в одном файле sensitive_settings_repo. Вы можете исследовать, как эта прозрачная технология шифрования работает с Git subodules http://git-scm.com/book/en/Git-Tools-Submodules, если вам действительно нужны конфиденциальные файлы в одном хранилище.

Использование фиксированной кодовой фразы может теоретически привести к грубой силе, если злоумышленники имеют доступ ко многим зашифрованным репозиториям/файлам. ИМО, вероятность этого очень низкая. В примечании в нижней части этого руководства упоминается, что использование фиксированной кодовой фразы приведет к локальным версиям репо на разных машинах, всегда показывающих, что изменения произошли с "git status".

Ответ 3

Heroku толкает использование переменных окружения для настроек и секретных ключей:

Традиционный подход для работы с такими конфигурационными vars заключается в том, чтобы помещать их в исходный код - в файл свойств какого-либо типа. Это процесс, подверженный ошибкам, и особенно сложен для приложений с открытым исходным кодом, которые часто должны поддерживать отдельные (и частные) ветки с конфигурациями, специфичными для приложения.

Лучшим решением является использование переменных среды и сохранение ключей вне кода. На традиционном хосте или работающем локально вы можете установить окружение vars в вашем bashrc. На Heroku вы используете config vars.

С файлами Foreman и .env Heroku предоставляет завидную инструментальную цепочку для экспорта, импорта и синхронизации переменных среды.


Лично я считаю неправильным сохранять секретные ключи вместе с кодом. Это принципиально несовместимо с контролем источника, потому что ключи предназначены для служб, которые являются неотъемлемой частью кода. Одним из преимуществ было бы то, что разработчик может клонировать HEAD и запускать приложение без какой-либо настройки. Однако предположим, что разработчик проверяет историческую ревизию кода. Их копия будет включать в себя пароль базы данных в прошлом году, поэтому приложение будет недоступно для сегодняшней базы данных.

С помощью метода Heroku выше разработчик может проверить прошлогоднее приложение, настроить его с помощью сегодняшних ключей и успешно запустить его с сегодняшней базой данных.

Ответ 4

Самый чистый способ, на мой взгляд, - использовать переменные среды. Например, вам не придется иметь дело с файлами .dist, а состояние проекта в рабочей среде будет таким же, как у вашей локальной машины.

Я рекомендую прочитать главу The Twelve-Factor App, остальные тоже, если вам интересно.

Ответ 5

Опция должна заключаться в том, чтобы поместить связанные с проектом учетные данные в зашифрованный контейнер (TrueCrypt или Keepass) и нажать его.

Обновить как ответ из моего комментария ниже:

Интересный вопрос кстати. Я просто нашел это: github.com/shadowhand/git-encrypt, который выглядит очень перспективным для автоматического шифрования

Ответ 6

Я предлагаю использовать файлы конфигурации для этого и не выполнять их.

Однако вы можете использовать примеры файлов.

Я не вижу проблем с совместным использованием настроек разработки. По определению он не должен содержать никаких ценных данных.

Ответ 7

BlackBox был недавно выпущен StackExchange, и пока я еще не использовал его, он, похоже, точно решает проблемы и поддерживает функции, заданные в этом вопросе.

Из описания https://github.com/StackExchange/blackbox:

Безопасное хранение секретов в репозитории VCS (т.е. Git или Mercurial). Эти команды упрощают для вас GPG шифрование определенных файлов в режиме репо поэтому они "зашифрованы в покое" в вашем репозитории. Однако скрипты упрощают их расшифровку, когда вам нужно просматривать или редактировать их, и расшифровать их для использования в производстве.

Ответ 8

Я задаю вопрос в целом, но в моем конкретном случае я бы хотел хранить секретные ключи и пароли для сайта Django/Python с помощью gitи github.

Нет, просто нет, даже если это ваше личное репо, и вы никогда не собираетесь делиться им, не делайте этого.

Вы должны создать local_settings.py поставить его на VCS игнорировать и в settings.py сделать что-то вроде

from local_settings import DATABASES, SECRET_KEY
DATABASES = DATABASES

SECRET_KEY = SECRET_KEY

Если ваши настройки секретов настолько универсальны, я очень хочу сказать, что вы что-то делаете неправильно

Ответ 9

EDIT: Я предполагаю, что вы хотите отслеживать свои предыдущие версии паролей - скажем, для script, которые предотвратили бы повторное использование паролей и т.д.

Я думаю, что GnuPG - лучший способ - он уже используется в одном проекте git (git -annex) для шифрования содержимого репозитория, хранящегося в облачных сервисах. GnuPG (gnu pgp) обеспечивает очень сильное шифрование на основе ключей.

  • Вы сохраняете ключ на своей локальной машине.
  • Вы добавляете "mypassword" к игнорируемым файлам.
  • В режиме pre-commit hook вы зашифровываете файл mypassword в файле mypassword.gpg, отслеживаемом git, и добавляете его в commit.
  • На крюке после слияния вы просто расшифровываете mypassword.gpg в mypassword.

Теперь, если ваш файл "mypassword" не изменился, тогда шифрование приведет к тому же зашифрованному тексту, и оно не будет добавлено в индекс (без избыточности). Небольшая модификация mypassword приводит к радикально различаемому зашифрованному тексту, а mypassword.gpg в промежуточной области сильно отличается от той, что находится в репозитории, поэтому будет добавлена ​​в фиксацию. Даже если злоумышленник завладеет вашим ключом gpg, ему все равно нужно переубедить пароль. Если злоумышленник получает доступ к удаленному репозиторию с зашифрованным текстом, он может сравнить кучу зашифрованных текстов, но их количество не будет достаточным, чтобы дать ему какое-либо незначительное преимущество.

Позже вы можете использовать .gitattributes, чтобы обеспечить дешифрование "на лету" для выхода из вашего пароля git.

Также вы можете иметь отдельные ключи для разных типов паролей и т.д.

Ответ 10

Предоставить способ переопределить конфигурацию

Это лучший способ управлять набором нормальных значений по умолчанию для конфигурации, которую вы проверите, не требуя завершения конфигурации, или содержать такие вещи, как имена хостов и учетные данные. Существует несколько способов переопределения конфигураций по умолчанию.

Переменные среды (как уже упоминалось ранее) - это один из способов сделать это.

Лучший способ - найти внешний файл конфигурации, который переопределяет значения конфигурации по умолчанию. Это позволяет вам управлять внешними конфигурациями через систему управления конфигурацией, такую ​​как Chef, Puppet или Cfengine. Управление конфигурацией - это стандартный ответ для управления конфигурациями отдельно от кодовой базы, поэтому вам не нужно делать выпуск для обновления конфигурации на одном хосте или группе хостов.

FYI: Шифрование кредитов не всегда является лучшей практикой, особенно в месте с ограниченными ресурсами. Возможно, шифрование кредитов не приведет к дополнительным смягчениям риска и просто добавит ненужный уровень сложности. Перед принятием решения убедитесь, что вы сделали правильный анализ.

Ответ 11

Обычно я разделяю пароль как файл конфигурации. и сделать их dist.

/yourapp
    main.py
    default.cfg.dist

И когда я запустил main.py, поместите настоящий пароль в default.cfg, который скопирован.

пс. когда вы работаете с git или hg. вы можете игнорировать файлы *.cfg, чтобы сделать .gitignore или .hgignore

Ответ 12

Зашифровать файл паролей, используя, например, GPG. Добавьте ключи на свой локальный компьютер и на свой сервер. Расшифруйте файл и поместите его за пределы своих репозиториев.

Я использую passwords.conf, который находится в моей домашней папке. При каждом развертывании этот файл обновляется.

Ответ 13

Нет, личные ключи и пароли не попадают под контроль версий. Нет никаких оснований для того, чтобы обременять каждого доступным для чтения к вашему репозиторию знанием конфиденциальных учетных данных службы, используемых в производстве, когда, скорее всего, не все из них должны иметь доступ к этим услугам.

Начиная с Django 1.4, ваши проекты Django теперь поставляются с модулем project.wsgi, который определяет application объект, и это идеальное место для начала использования модуля настроек project.local, который содержит настройки для конкретного сайта.

Этот модуль настроек игнорируется из контроля версий, но его присутствие требуется при запуске экземпляра проекта в качестве приложения WSGI, типичного для производственных сред. Вот как это должно выглядеть:

import os

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.local")

# This application object is used by the development server
# as well as any WSGI server configured to use this file.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

Теперь у вас может быть модуль local.py, владелец и группа которого могут быть настроены таким образом, чтобы только пользовательский персонал и процессы Django могли читать содержимое файла.

Ответ 14

Если вам нужны VCS для ваших секретов, вы должны хотя бы сохранить их во втором хранилище, отделенном от вашего фактического кода. Таким образом, вы можете предоставить членам вашей команды доступ к репозиторию исходного кода, и они не будут видеть ваши учетные данные. Кроме того, размещайте этот репозиторий где-нибудь в другом месте (например, на своем собственном сервере с зашифрованной файловой системой, а не на github), и для проверки его в производственной системе вы можете использовать что-то вроде git -подмодуль.

Ответ 15

Другой подход может заключаться в том, чтобы полностью избежать сохранения секретов в системах управления версиями и вместо этого использовать такой инструмент, как хранилище из hashicorp, секретное хранилище с ключом катив и аудит, с API и встроенным шифрованием.

Ответ 16

Вы можете использовать EncFS, если ваша система предоставляет это. Таким образом, вы можете хранить ваши зашифрованные данные в виде подпапки вашего репозитория, предоставляя приложению ваше дешифрованное представление к данным, собранным в стороне. Поскольку шифрование является прозрачным, никаких специальных операций не требуется при нажатии или нажатии.

Тем не менее, необходимо будет установить папки EncFS, которые могут быть выполнены вашим приложением на основе пароля, хранящегося в другом месте за пределами версий версий (например, переменных среды).