Почему пароль от базы данных никогда не должен жить в конфигурационном файле

Вы создаете новое приложение. На раннем этапе вы помещаете все переменные данные в один файл: имя базы данных, адрес сервера, URL-адреса API. Он попадает в Git, отправляется в репозиторий и разворачивается на сервере. Все в одном месте, и это кажется практичным. Затем вы добавляете в тот же файл пароль базы данных. Потом токен API. Потом ключ шифрования. Внезапно этот единственный конфигурационный файл становится угрозой безопасности, способной обрушить всю вашу систему.

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

Разница между конфигурацией и секретом

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

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

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

Что происходит, когда секрет утекает

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

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

История Git усугубляет ситуацию. Даже если вы удалите файл, содержащий секрет, секрет останется в истории коммитов. Любой, кто клонирует репозиторий, может выполнить git log и найти пароль, который, как вы думали, удалили. Не существует простого способа полностью очистить историю Git, особенно если репозиторий был опубликован или форкнут.

Как конфигурация и секреты различаются на практике

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

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

Где они хранятся: Конфигурация может храниться в Git. Секреты никогда не должны храниться в Git. Они принадлежат выделенной системе хранения секретов, которая шифрует их в состоянии покоя и при передаче.

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

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

Практические последствия путаницы между ними

Когда вы относитесь к секретам как к конфигурации, вы создаете цепочку проблем, которые трудно исправить.

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

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

В-третьих, вы нарушаете аудиторский след. Если секрет утекает, вам нужно знать, кто имел к нему доступ и когда. Если секрет был в Git, ответ — «все, кто когда-либо имел доступ к репозиторию». Это бесполезный аудиторский след.

Простой способ отличить одно от другого

Прежде чем помещать какие-либо данные в конфигурационный файл, задайте себе один вопрос: «Если кто-то за пределами моей команды увидит это, сможет ли он использовать это для доступа к моей системе?»

Если ответ отрицательный, это, вероятно, конфигурация. Имена серверов, номера портов, функциональные флаги и уровни логирования — это конфигурация.

Если ответ положительный, это секрет. Пароли баз данных, токены API, SSH-ключи, ключи шифрования и учетные данные сервисных аккаунтов — это секреты.

Этот простой тест предотвратит большинство распространенных ошибок, которые допускают команды.

Практический чек-лист для работы с секретами

Когда вы настраиваете свой следующий проект или проверяете текущий, пройдитесь по этому чек-листу:

  • Все ли секреты хранятся вне Git? Используйте выделенный менеджер секретов или хранилище.
  • Внедряются ли секреты во время выполнения, а не вшиваются в образы или артефакты?
  • Получают ли ваши конвейеры CI/CD секреты из безопасного источника, а не из файлов репозитория?
  • Исключены ли секреты из логов, сообщений об ошибках и отладочного вывода?
  • Есть ли у вас график ротации для каждого типа секретов?
  • Существует ли процесс немедленной ротации секретов при подозрении на утечку?
  • Можете ли вы отозвать доступ к секретам для конкретных людей или систем, не затрагивая других?

Вывод

Если часть данных может быть использована кем-то другим для выдачи себя за вас или вашу систему, это не конфигурация. Это секрет. Относитесь к нему иначе. Храните его отдельно. Ротируйте его регулярно. И никогда, никогда не коммитьте его в Git. Цена изучения этого урока на собственном горьком опыте намного выше, чем усилия, затраченные на правильные действия с самого начала.