it-swarm.com.ru

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

Я хочу услышать некоторые лучшие практики ...

Предполагая, что веб-приложение взаимодействует с несколькими различными производственными серверами (базами данных и т.д.) ... должны ли файлы конфигурации, содержащие пароли баз данных, храниться в системе контроля версий (например, git, svn)?

Если нет, то как лучше всего отслеживать пароли базы данных сервера (или других связанных) паролей, к которым вашему приложению необходим доступ?

Правка: добавил награду, чтобы поощрить больше обсуждений и услышать, что больше людей считают лучшей практикой.

50
philfreo

Здесь нет единственного ответа «серебряной пули», и все это будет сильно зависеть от деталей.

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

Если у вас есть отдельный репозиторий исходного кода + репозиторий развертывания, вам лучше всего подумать о вариантах развертывания. Лучший способ, который я вижу здесь, - это использование процедур развертывания, типичных для выбранной ОС (то есть создание автономных пакетов для выбранной ОС так, как это делают сопровождающие ОС).

Например, процедуры упаковки Red Hat или Debian обычно означают получение архива программного обеспечения с внешнего сайта (который будет экспортировать источники из вашего исходного кода VCS), его распаковку, компиляцию и подготовку пакетов, готовых к развертыванию. Само развертывание в идеале должно означать простую и быструю команду, которая установит пакеты, такие как rpm -U package.rpm, dpkg --install package.deb или apt-get dist-upgrade (учитывая, что ваши собранные пакеты идут в репозиторий, где apt-get сможет их найти).

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

Чтобы получить более краткие сведения, давайте рассмотрим типичную ситуацию «небольшого сервиса»: одно приложение PHP развернуто на n серверах приложений, работающих под Apache/mod_php, обращаясь к m серверам MySQL. Все эти серверы (или виртуальные контейнеры, что на самом деле не имеет значения) находятся в защищенной частной сети. Чтобы упростить этот пример, давайте предположим, что все реальные подключения к Интернету предоставляются кластером k http ускорителей/обратных прокси (таких как nginx/lighttpd/Apache), которые имеют очень простую конфигурацию (только внутренние IP-адреса для пересылки на ).

Что нам нужно, чтобы они были подключены и полностью работали?

  • Серверы MySQL: настройте IP-адреса/имена хостов, настройте базы данных, предоставьте логины и пароли
  • PHP-приложение: настройте IP-адреса/имена хостов, создайте файл конфигурации, в котором будут указаны IP-адреса, логины, пароли и базы данных серверов MySQL.

Обратите внимание, что здесь есть 2 разных «типа» информации: IP-адреса/имена хостов являются чем-то фиксированным, вы, вероятно, захотите назначить их раз и навсегда. С другой стороны, логины и пароли (и даже имена баз данных) предназначены исключительно для целей подключения - чтобы убедиться, что для MySQL это действительно наше приложение PHP, подключающееся к нему. Итак, мои рекомендации здесь будут разделять эти 2 "типа":

  • «Постоянная» информация, такая как IP, должна храниться в некоторых VCS (отличается от исходного кода VCS)
  • «Переходная» информация, такая как пароли между двумя приложениями, никогда не должна храниться, а должна генерироваться во время генерации пакетов развертывания.

Последний и самый сложный вопрос остается здесь: как создавать пакеты развертывания? Есть несколько доступных методов, 2 основных способа:

  • Экспортированный исходный код из VCS1 + «постоянная» конфигурация из VCS2 + сценарий сборки из VCS3 = пакетов
  • Исходный код находится в VCS1; VCS2 - это распределенный контроль версий (например, git или hg), который по существу содержит «вилки» VCS1 + информация о конфигурации + сценарии сборки, которые могут генерироваться. Мне лично этот подход нравится больше, он намного короче и в конечном итоге проще в использовании, но кривая обучения может быть немного круче, особенно для администраторов, которым для этого придется освоить git или hg.

Для примера выше, я бы создал пакеты, такие как:

  • my-application-php - который будет зависеть от mod_php, Apache и будет содержать сгенерированный файл, такой как /etc/my-php-application/config.inc.php, который будет содержать IP-адреса/имена хостов базы данных MySQL и логин/пароль, сгенерированные как md5(current source code revision + salt). Этот пакет будет установлен на каждом из n серверов приложений. В идеале он должен быть в состоянии установить на чисто установленную ОС и сделать полностью работающий узел кластера приложений без каких-либо ручных действий.
  • my-application-mysql - который будет зависеть от MySQL-сервера и будет включать в себя скрипт после установки, который:
    • запускает сервер MySQL и обеспечивает автоматический запуск при запуске ОС
    • подключается к серверу MySQL
    • проверяет, существует ли необходимая база данных
    • если нет - создает базу данных, загружает ее с содержимым и создает логин с паролем (те же логины и пароли, которые были сгенерированы в /etc/my-php-application/config.inc.php с использованием алгоритма md5)
    • если да - подключается к базе данных, применяет миграции, чтобы привести ее к новой версии, убивает все старые логины/пароли и воссоздает новую пару логин/пароль (опять же, сгенерированную с использованием метода md5 (revision + salt))

В конечном счете, это должно принести пользу при обновлении развертывания с помощью одной команды, например generate-packages && ssh-all apt-get dist-upgrade. Кроме того, вы нигде не храните пароли между приложениями, и они обновляются при каждом обновлении.Этот довольно простой пример иллюстрирует множество методов, которые вы можете использовать здесь, но, в конечном счете, вам решать, какое решение лучше здесь, а какое - излишним. Если вы укажете подробности здесь или в качестве отдельного вопроса, я с удовольствием постараюсь вникнуть в детали.

This fairly simple example illustrates a lot of methods you can employ here - but, ultimately, it's up to you to decide which solution is better here and which one is overkill. If you'll put more details here or as a separate question, I'll gladly try to get into details.

27
GreyCat

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

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

Если бы мы могли найти способ проверить физическое оборудование, мы бы тоже это сделали :-)

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

18
paxdiablo

Пароли не должны храниться в системе контроля версий. Совсем. Когда-либо. Смотрите Как хранить секреты в секрете

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

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

Все остальное, кроме конфигурации сервера должно находиться в системе контроля версий.

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

Всегда храните эти файлы конфигурации вне webroot.

Доверенные соединения могут быть опцией, позволяющей известным IP-адресам подключаться к службам путем настройки этой службы. 

11
Richard Harrison

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

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

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

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

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

7
Marnix van Valen

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

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

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

3
8DH

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

1
Jinesh Parekh

В моих репозиториях Subversion для PHP файлы конфигурации, содержащие пароли, отмечаются как config.php.sample с подсказками о том, что должно быть предоставлено, а сценарии, полагающиеся на то, что config.php должны присутствовать в том же месте.

Репозиторий настроен на игнорирование config.php для этого каталога, чтобы избежать «случайных» добавлений или проверок.

1
Linus Kleen

Проблемы с паролями в исходном коде:

  • трудно варьировать от одного развертывания к другому (я не хочу изменять исходный код в рабочей среде)
  • повышенная вероятность случайного повреждения производственной базы данных при разработке
  • проблема безопасности (в большинстве магазинов нет причин, по которым код/​​разработчики должны знать пароли prod)
  • измененный пароль требует перераспределения

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

Примечание. Когда я работаю как администратор, я всегда управляю конфигами отдельно от кода (по уважительной причине).

1
dietbuddha

Я обнаружил, что использование сценария сборки (в моем случае Phing) - лучший способ ввода паролей.

1
Matt Bostock

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

 # program.conf 
 # 
 # mysql опция для $ myprog .
 # 
 # SERVER_ADDR = 127.0.0.1 
 # SERVER_USER = mysql 
 # SERVER_PASSWD = abcdef .__ ,
1
user502515

Я предпочитаю иметь local_settings file рядом с основным settings file. Этот local_settings не следует добавлять в репозиторий, но я добавлю sample.local_setting в репозиторий, чтобы показать структуру этого файла.

Во время выполнения, если local_settings существует, его значения будут переопределять значения файла основных настроек.

Например в питоне:

settings.py:

log='error.log'
db=lambda:None
db.Host='localhost'
db.user=''
db.password=''

try:
    import local_settings
except ImportError:
    pass

local_settings.py:

from settings import *

db.user='abcd'
db.password='1234'
0
iman

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

0
Matthew Morek

Без правильного процесса сборки я использую эту стратегию (для PHP приложений):

  1. Сделать папку /etc/companyname
  2. В нем поместите два файла:

    <?php // env.php
    return 'prod'; 
    
    <?php // appname-prod.php
    return array(
      'db' => array( /* credentials */ ),
      /* other Host-specific conf data */
    ); 
    
  3. Сделайте оба файла доступными для чтения только вашим процессом PHP

Теперь файл конфигурации вашего приложения будет выглядеть примерно так:

<?php // config.php
$env = (require "/etc/companyname/env.php");
$creds = (require "/etc/companyname/appname-{$env}.php");

После этого среда определяет используемые учетные данные, и вы можете перемещать код между предварительно настроенными средами (и управлять некоторыми параметрами с помощью $env). Это, конечно, можно сделать с помощью переменных среды сервера, но это а) проще в настройке и б) не предоставляет учетные данные для каждого скрипта на сервере (не будет отображаться в нежелательной отладке типа phpinfo()).

Для более легкого чтения за пределами PHP вы могли бы сделать файлы учетных данных JSON или что-то в этом роде и просто мириться с крошечным ударом по производительности (APC не будет их кэшировать).

0
Steve Clay