Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

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

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

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

  • Экспортированный исходный код из VCS1 + "постоянная" конфигурация из здания VCS2 + script из 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 серверов приложений. В идеале, он должен быть способен установить на чистой установленной ОС и сделать полностью работающий кластер приложений node без каких-либо ручных действий.
  • my-application-mysql - который будет зависеть от MySQL-сервера и будет включать post-install script, который:
    • запускает сервер MySQL и гарантирует, что он запустится автоматически при запуске ОС
    • подключается к серверу MySQL
    • проверяет наличие существующей базы данных
    • if no - создает базу данных, загружает ее содержимым и создает логин с паролем (те же логины и пароли, что и сгенерированные в /etc/my-php-application/config.inc.php, используя алгоритм md5)
    • если да - подключается к базе данных, применяет миграцию, чтобы довести ее до новой версии, убивает все старые логины/пароли и воссоздает новую пару логин/пароль (опять же, сгенерированный с использованием метода md5 (версия + соль))

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

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

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

Ответ 8

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

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

Ответ 9

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

# program.conf
#
# mysql option for $myprog.
#
#SERVER_ADDR=127.0.0.1
#SERVER_USER=mysql
#SERVER_PASSWD=abcdef

Ответ 10

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

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

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

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

Ответ 11

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

Ответ 12

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

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

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

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

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

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

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

Ответ 13

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

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

Например, в python:

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'