От коммита до работающего сервиса
От изменения до выпуска
Вид
Текст20

Начальный · Глава 1 / 18

Среда: приложение должно знать, где оно работает

После главы: Разделить код, конфигурацию и секреты перед первым выпуском.

В этой главе

Три разных вида сведений

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

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

Проверка до приёма запросов

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

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

Удобный локальный запуск и доверенная среда

У assert есть режим отключения: Python с -O убирает такие проверки. Поэтому обязательное ограничение режима реализуют явным отказом, а assert оставляют для проверки примера. В CI недоверенная ветка или внешний pull request не должны получать секреты публикации только потому, что запускается знакомый workflow.

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

Ошибочный параметр должен быть заметен

Строка «false» непустая, поэтому наивное преобразование строки в логическое значение в некоторых языках даст истину. Это особенно неприятно для флага демонстрационной оплаты. Задайте небольшой допустимый набор значений и отклоняйте всё остальное. Для числа проверьте диапазон и единицу, для пути — ожидаемое назначение, для адреса — схему и разрешённую среду. Непонятный параметр нельзя молча заменять удобным значением по умолчанию, если от него зависит доступ или выбранная база.

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

Рассмотрите ошибку «тестовый режим включён на публичном адресе». Одного скрытого переключателя интерфейса недостаточно. Серверная политика должна отклонять недопустимую комбинацию режима, окружения и провайдера. Проверка включает отрицательный запуск с намеренно неверным сочетанием в отдельном стенде. Ожидается объяснимая остановка без сетевого действия. Так условие выпуска становится исполнимым, а оператор не обязан помнить каждую опасную комбинацию из длинной инструкции.

Разобранный пример

Локальный паспорт среды

Это локальный пример без секретов и внешних подключений. validate_local проверяет только этот учебный стенд; production-конфигурация требует собственного договора. Ошибки запуска выражены через ValueError: assert ниже проверяет пример, а не охраняет рабочую границу.

python
def validate_local(config):
    if config.get("mode") != "local":
        raise ValueError("Нужен локальный режим")
    if config.get("origin") != "http://127.0.0.1:8800":
        raise ValueError("Неожиданный адрес")
    if config.get("payments") != "disabled":
        raise ValueError("Платежи должны быть отключены")
    return config

config = {
    "mode": "local",
    "origin": "http://127.0.0.1:8800",
    "payments": "disabled",
}
assert validate_local(config) is config

Теперь самостоятельно

Практика

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

Результат: Таблица параметров без настоящих значений и одно правило запуска.

Подсказка
  • В шаблоне можно хранить название секретной переменной, но не её действующий ключ.
Решение и проверка

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

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

Проверьте себя без текста

Почему переменная окружения не равна защите?

Значение может попасть в журнал, процесс или клиентскую сборку.

Зачем разделять хранилища сред?

Чтобы учебная проверка не меняла рабочие данные и не получила лишний доступ.

Проверить по первоисточникам

Конец образца

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