Каков предпочтительный способ хранения конфигураций приложений?

38

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

app
|-- config.json

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

12 Руководство по Factor App рекомендует полностью удалить файлы конфигурации и использовать переменные среды для настройки конфигурации:

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

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

Существует ли какой-либо общепринятый способ обработки параметров конфигурации, в котором нет риска сохранения локальной конфигурации в системе контроля версий?

Рогач
источник
1
Ну, у git есть, по крайней мере, что-то вроде того, .gitignoreгде я могу определять файлы или папки, которые не должны проверяться в управлении версиями. Как вы говорите, я не вижу, в чем действительно могут помочь Env vars, у вас есть скрипт для их установки, который должен храниться вместе с проектом или у вас они «где-то» в вашей системе (домашний каталог или даже при запуске компьютеров). скрипты), что само по себе создает множество проблем, особенно если необходимо много настроек. В любом случае я бы разделил файлы конфигурации так, чтобы конфиденциальная информация помещалась в разные файлы.
Торстен Мюллер
@ thorstenmüller - проблема только с .gitignore в том, что базовая / шаблонная конфигурация все еще должна храниться, что означает, что приложение должно читать две конфигурации: базовую, с параметрами по умолчанию (хранится в scm) и локальную, которая переопределяет базу (и не хранится в scm). С помощью env vars я представляю, что массовое развертывание становится проще - проще указать переменные среды для новой настройки виртуальной машины, чем записать что-то в какой-то нестандартный файл.
Рогач
Хороший вопрос, после того, как я начал использовать обычное хранилище данных для пользовательских приложений, жизнь стала проще ;-)
Wolf
1
Вы пробовали "Redis" redis.io . Он предназначен специально только для хранения структуры ключ-значение.
Каран
2
@jporcenaluk - мне действительно нравятся хранилища ключей-значений, но добавление полнофункционального redis-приложения в приложение только для управления конфигурацией кажется излишним. С другой стороны, возможно, я никогда не работал над достаточно большими проектами.
Рогач

Ответы:

16

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

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

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

kiwiron
источник
2
Наличие двух отдельных репозиториев для одного проекта кажется плохой идеей - вы не можете выполнять чистые откаты или работать с ветками, потому что тогда вам нужно будет манипулировать двумя репозиториями одновременно (например, для другой ветки требуется новый параметр конфигурации, и когда вы переключитесь на эту новую ветку, не переключаясь в хранилище конфигурации, все происходит странным образом).
Рогач
2
@Rogach Я понимаю твою точку зрения. Существуют веские причины сохранять некоторую конфигурацию с кодом, но, как вы говорите в своем вопросе, чувствительные вещи должны идти куда-то еще. Таким образом, два хранилища кажутся неизбежными. Также я не упомянул, что серверы приложений здесь часто помогают. Источники данных и переменные JNDI могут быть установлены администратором и не будут общедоступными.
Кивирон
Второй магазин имеет смысл. Возможно, существуют другие виды данных, также конфиденциальные, которые могут храниться вместе с конфигурацией (например, производственные данные, которые анализируются для решения проблем клиентов).
Волк
1
@Rogach Они, кажется, привлекают много ненависти, но подмодули git справились бы с этим, я думаю, если бы основной был настроен правильно, и репо с ограниченным доступом могло бы просто жить внутри него.
SeldomNeedy
9

При рассмотрении проблем и возможных решений мне помогает метод, популярный у Джеффа Этвуда : если бы Бог создал способ хранения конфиденциальной информации о конфигурации, как бы он это сделал?

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

О первой части уже следует позаботиться: ваша система контроля версий должна проходить аутентификацию пользователей. И этому подходу также дают силу согласно # 10 в 10 заповедях Троя Ханта «Контроль источника» , «зависимости должны находиться в управлении источником».

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

jporcenaluk
источник
3
Просто хотел уточнить - как поможет конфигурация шифрования? Насколько я понимаю, вы должны будете сообщать всем разработчикам один и тот же пароль для расшифровки, и это звучит как вызов проблем.
Рогач
Если кто-то за пределами вашей компании получает доступ к вашему хранилищу, ваши пароли будут скрыты. Если кто-то копирует файлы из проекта на USB-накопитель и оставляет его где-то, то же самое. Конечно, будет больше работы для поддержания. Больше безопасности обычно достигается за счет удобства. Это решение немного громоздко, я дам вам это. Я открыт для лучшего способа решить вопрос ОП!
jporcenaluk
5

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

  • Простота реализации на любом языке. Во многих вы получаете поддержку сложных файлов конфигурации из коробки. Например, в случае Java с Spring Boot вы получаете поддержку YAML, которая может выражать любую древовидную структуру, и легко иметь отдельные файлы конфигурации для разных сред, а также базовую конфигурацию, от которой могут наследоваться специфичные для среды файлы.
  • Конфигурация необходима для запуска вашего программного обеспечения, а изменения в коде часто требуют добавления / изменения параметров конфигурации, поэтому естественно сохранять конфигурацию и код вместе.
  • Хранение конфигурации с исходным кодом дает вам все преимущества управления исходным кодом, например, знание, кто изменил какой параметр и когда, или возможность проверять конфигурации во время регулярного просмотра кода.
  • Если вы не работаете на ЦРУ, аргумент безопасности кажется мне раздутым. Таким образом, пароль вашей базы данных хранится в файле на компьютере, где работает ваше приложение. Что ж, если кто-то получит доступ к компьютеру с помощью вашего приложения, вы, вероятно, уже столкнулись с большими проблемами - он может, например, закрыть ваше приложение и запустить свое собственное приложение на том же порту. В таком случае доступ к паролю БД может не быть такой большой проблемой. Если все ваши соединения не будут полностью зашифрованы и не имеют доступа к вашему компьютеру, они все равно могут прослушивать большую часть интересных данных с сетевых интерфейсов.
  • Вы можете использовать такой инструмент, как Hiera, чтобы иметь текстовый файл конфигурации, но не хранить в нем пароли или другие конфиденциальные данные.

Поэтому во многих случаях текстовая конфигурация, хранящаяся в системе контроля версий вместе с кодом, является хорошим началом.

Если вы работаете в распределенных системах или хотите иметь возможность горячей замены конфигурации без повторного развертывания приложений, вы можете лучше найти решение, основанное на сервере конфигурации. Spring Cloud поддерживает такие механизмы , и конфигурациями серверной части могут быть Git-репозиторий или Eureka . Вы также можете свернуть свои собственные, используя, например, Zookeeper . Любой из этих подходов облегчит управление согласованными конфигурациями на многих серверах, чтобы обновлять конфигурации без необходимости перестраивать и повторно развертывать программное обеспечение. Это, конечно, обходится дорого: изучение сервера конфигурации и его использования из ваших приложений, а также еще одной системы для развертывания и обслуживания.

Михал Космульский
источник
Но код переходит к другому человеку, который не владеет секретами в конфигурационных файлах, там будет настоящий беспорядок.
Тим Людвински
@TimLudwinski Ключи / секреты принадлежат компании, а не отдельным разработчикам, поэтому их следует поддерживать таким образом, чтобы они не потерялись, если кто-то из них уйдет. Например, они могут быть проблемами и поддерживаться администраторами / командой безопасности, так что существует центральный реестр.
Михал
5

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

Тем не менее, я думаю, что мы нашли хорошее решение в будущем. Мы перемещаем наши файлы конфигурации в отдельное git-репо (помеченное как config-репо). Затем мы настраиваем сервер spring-cloud-config (java), который просто обслуживает файлы из репозитория config на основе переданных ему профилей. Это отлично подходит для приложений Java, которые могут использовать клиент и загружать их во время запуска. Для наших PHP / не Java-приложений мы будем извлекать файл напрямую. (Не идеально). В будущем мы можем написать что-то, что позволит PHP-приложению самостоятельно загружать конфигурации и кэшировать их где-то, но это не является первоочередной задачей для первого запуска. Я рассматриваю это решение как конфигурацию как услугу, которая явно не нарушает рекомендации 12-факторных приложений.

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

Ссылки:

https://spring.io/guides/gs/centralized-configuration/

https://cloud.spring.io/spring-cloud-config/

ssjcory
источник
3

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

  • Есть каталог конфигурации . Все файлы там интерпретируются как файлы конфигурации, за исключением, может быть README*.
  • Все имена файлов отсортированы в алфавитном порядке, и файлы загружаются в указанном порядке. Именно поэтому файлы в таких случаях часто начинаются с цифры или два: 01-logging.json. 02-database.json, так далее.
  • Данные из всех файлов загружаются в ту же структуру конфигурации, которая доступна для приложения. Вот как несколько файлов могут дополнять настройки друг друга и даже переопределять их предсказуемым образом.
  • Храните в VCS только файлы конфигурации с безопасными для просмотра значениями или значениями по умолчанию. Добавьте файлы конфигурации с секретами во время развертывания или, что еще лучше, используйте службу хранения аутентифицированных секретов.

На ближайшем к вам Linux-сервере посмотрите /etc/sudoers.dили /etc/nginx/conf.d. Это показывает ту же картину.

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

(Также, часть мнения: JSON не является хорошим форматом файла конфигурации, потому что он не допускает комментарии; комментарии имеют решающее значение. Форматы TOML, YAML и даже INI лучше в практическом использовании.)

9000
источник
2

Я думаю, что ваши параметры в некоторой степени определяются операционной системой, в которой вы развертываете

Я хотел бы предложить, да поставить значения в системе контроля версий. НО только версии 'dev'. Вы хотите, чтобы ваш исходный код компилировался и работал! не включать дополнительные секретные шаги

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

Ewan
источник
0

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

Gmoney
источник
6
Какие есть варианты? как это работает? Где он хранит их? Один предпочтительнее другого? Каковы различные преимущества и недостатки каждого варианта? Как это взаимодействует в разных операционных системах?
3
@Gangz - Мне был бы интересен более подробный ответ, пожалуйста, не разочаровывайтесь от отрицательных голосов, и улучшите свой ответ, чтобы он мог помочь.
Джей Элстон