Проверьте три утверждения на своём ландшафте:

  1. Есть стенд, который называется testuat или pilot, и при этом он читает реальные данные.

  2. Есть хост, по имени которого машина не может сказать, к какому окружению он относится и какой системе принадлежит.

  3. Политики доступа пишутся списками IP-адресов, потому что имена ресурсов ничего не значат.

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

Имя — это не этикетка

Привычная точка зрения: имя хоста — вопрос удобства. srv-msk-prod-db-tier1-old-02 — «ну понятно же». Понятно человеку, который его придумал. Машине — нет.

Такое имя нельзя распарсить, нельзя проверить регулярным выражением в CI, нельзя положить в политику доступа. Хуже: оно врёт при каждом изменении. Переехали в другой ЦОД, понизили критичность, вывели «old» из эксплуатации — имя осталось.

EnvSpec Naming предлагает считать имя не этикеткой, а адресом в строгой системе координат. Тогда из имени однозначно следует: чей это ресурс, в каком режиме доверия он живёт и с кем ему можно разговаривать.

Пять уровней и одно правило

Стандарт задаёт иерархию окружение → контур → стенд → слот → узел. Каждый уровень принадлежит ровно одному родителю. Из неё собирается канонический FQDN:

{node}.{slot}.{system}.{perimeter}.{env}.{domain}
db-01.main.billing.payments.prod.example.ru

Ключевая деталь — порядок «от частного к общему» и суффикс-окружение. Имя становится распознаваемым любым инструментом: от grep до Validating Webhook в Kubernetes. Те же компоненты проецируются в SPIFFE ID, имя namespace, облачный проект, схему СУБД и три обязательных тега envspec.io/envenvspec.io/perimeterenvspec.io/system. Расхождение слоёв — нарушение стандарта, и оно проверяется автоматически.

В имени запрещено кодировать изменчивые свойства: площадку, SLA, класс критичности, статус жизненного цикла, роль сотрудника. Версии и релизные группы (blue-green, канарейки) живут только в слоте: app-01.v2.antifraud.risk.test, а не antifraud-v2.

Окружений шесть. Больше не будет

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

Критерий принадлежности единственный: кто потребители и какие данные обрабатываются. Не железо, не площадка, не стадия проекта, не бюджет.

Отсюда заголовок. Стенд UAT, на который «для приёмки» залили боевую выгрузку — это prod по определению. Пилот, который «только читает» реальные данные — prod. Стандарт не знает «stage с исключением»: он требует отдельный контур prod (uat.prodpilot.prod) и все меры защиты prod. Не потому, что так строже, а потому, что данные уже там.

Два окружения стоят вне линейной шкалы:

  • infrastructure — CI/CD, секреты, реестры артефактов, каталоги, мониторинг, бэкапы. Обслуживает все окружения, поэтому защищается не слабее prod: компрометация раннера равна компрометации prod. И не может быть транзитным каналом prod → test.

  • workplace — рабочие места. Недоверенное устройство по определению. Роль сотрудника в имени не кодируется, доступ к любому окружению — только через шлюз доступа.

Что из этого следует для ИБ

Главные правила доверия между окружениями (раздел 3.6) :

  1. Стенды разных окружений линейной шкалы напрямую не взаимодействуют.

  2. infrastructure — единственное окружение, стендам которого разрешено взаимодействие со всеми: управляющие потоки вниз (артефакты, секреты), телеметрия вверх (логи, метрики).

  3. Рабочие места ходят в любое окружение только через шлюз доступа этого окружения.

  4. Внешние системы представлены контуром external.{env} и общаются только со стендами своего окружения — через шлюз.

Дальше несколько примеров. Зелёное разрешено, красное запрещено.

Сценарий 1. Личный кабинет банка: DMZ, контрагент и одно «временно»

  • DMZ — это не окружение. Это контур dmz.prod. Компонент, который живёт в DMZ — отдельный цифровой актив lk-ui со своим мнемокодом, а не «фронт того же lk». Иначе имя врёт о границе доверия.

  • Контрагент — это companyid.external.prod. Его песочница — companyid.external.test. Имена разные, окружения разные, и правило 3.6.4 запрещает боевому стенду ходить в песочницу, даже когда «у контрагента прод лежит». Политика на egress-шлюзе пишется по суффиксу имени, а не по IP.

  • «Временно» — это навсегда. lk-api.web.test, читающий db-01.main.abs.core.prod — нарушение 3.6.1. И одновременно диагноз: этот стенд уже prod, просто не назван так.

  • Ноутбук разработчика — laptop-17.main.laptop.office.workplace. Он не становится доверенным от того, что подключился по VPN «внутрь». Путь к узлу prod один: через pam.platform.prod.

Сценарий 2. Конвейер доставки: ваш CI-раннер — это prod

  • Раннер деплоит в prod — значит, он prod. runner-24.main.gitlab.cicd.infrastructure имеет доступ к kube1.platform.prod. Его режим защиты по стандарту — не ниже prod. Спросите себя, так ли это сейчас.

  • Общий стенд — не общий канал. Логи prod и test в одном loki допустимы, но раздельными арендаторами. Чтение боевых журналов с персональными данными из test «для воспроизведения бага» — транзит prod → test через infrastructure, запрещённый 3.2.

  • Namespace — это проекция стенда. billing-payments-prod, а не prod-payments-billing: порядок от частного к общему сохраняется и здесь, иначе одна регулярка на весь ландшафт не сработает.

  • Kubeconfig с admin-токеном на ноутбуке — то же нарушение 3.5, что и SSH мимо bastion. Ноутбук — workplace, кластер — prod, между ними должен быть шлюз.

Сценарий 3. Три пилота: окружение выбирает цель, а не слово «пилот»

  • Посмотреть функции — test. Пилот BI-платформы: бизнесу нужно покликать отчёты, вендору — показать продукт. Данные — синтетика, смежные системы — копиями внутри контура: bi-01.app.bi.pilot.test. Инженер вендора — такой же субъект доступа с рабочего места, как и сотрудник: VDI-сессия vdi-07.main.vdi.remote.workplace, учётная запись в корпоративном каталоге и вход только через pam.platform.test (3.3, 3.5). «Вендор» в имени рабочего места не кодируется — это роль, а роль живёт в каталоге. Вендор «настроил интеграцию» с боевой АБС db-01.main.abs.core.prod? Это test → prod, нарушение 3.6.1, и политика по суффиксу имени отрежет её раньше, чем вы дочитаете договор.

  • Проверить нагрузку — stage. Пилот нового антифрод-движка: вопрос не «что он умеет», а «выдержит ли боевой профиль транзакций». Конфигурация — зеркало prod, данные — синтетика по профилю prod или обезличенный срез, причём обезличивание выполняется на стороне prod до пересечения границы (3.1): antifraud.pilot.stage. «Снимем боевой трафик и проиграем на стенде» — это боевые данные в stage: стенд уже prod.

  • Нужны реальные данные — prod. Пилот CRM на фокус-группе сотрудников филиала без реальных клиентов в базе и реальной истории обращений бессмыслен, значит — crm.pilot.prod со всеми мерами prod и последствиями по 152-ФЗ (3.1). Фокус-группа работает с АРМ arm-42.main.arm.office.workplace — это workplace, а не часть prod: аудиторию ограничивает политика на ingress.platform.prod, а не понижение окружения до test «чтобы не тащить требования». Размер аудитории окружение не меняет.

  • Пилот — это контур, и он заканчивается. pilot — один и тот же идентификатор контура в трёх окружениях, но три разных набора требований: их задаёт суффикс, а не название проекта. И не площадка: test и stage живут в публичном облаке, prod — в собственном ЦОД, но в имени этого нет — площадка ортогональна иерархии и ведётся тегом envspec.io/site (3.7). Продукт выбран — стенд переезжает в постоянный контур (crm.sales.prod). Не выбран — контур ликвидируется целиком. Пилот, который «пять лет как прод», но по-прежнему живёт в pilot.prod — имя врёт о назначении так же, как old в имени хоста.

Сценарий 4. Общее S3: сервисы в Kubernetes, коммунальный S3, ключи в Vault

  • Общее хранилище — это s3.platform.prod. Целиком. Актив, который обслуживает несколько контуров одного окружения, размещается один раз в зарезервированном контуре platform (3.4). Что оно стоит на физических серверах в своём ЦОД, из имени не видно: узел node-03.main.s3.platform.prod, площадка и тип железа — в тегах (3.7). Оно хранит боевые объекты, значит — prod по определению (3.1), вместе с консолью и оператором. Разнести Control Plane в infrastructure стандарт допускает (3.2), но не требует. А вот «положим всё S3 в infrastructure, там защита всё равно не ниже» — нельзя: infrastructure хранит секреты, артефакты и журналы, а не боевые данные (3.2).

  • Кластер — тоже стенд platform.prod, namespace — проекция стенда-потребителя. Узлы worker-11.main.kube1.platform.prod принадлежат платформенному контуру, а сервисы на них — своим контурам: namespace billing-payments-prod, SPIFFE ID spiffe://example.ru/env/prod/perimeter/payments/system/billing/slot/api, бакет billing-payments-prod — три проекции одного стенда. Политика бакета сверяет SPIFFE ID клиента с именем бакета: потребители разграничиваются средствами самого актива, а не отдельным S3 на каждый контур (3.4). «Один root-ключ на всё хранилище, чтобы не возиться с политиками» — и antifraud-risk-prod читает бакет billing: разграничения по 3.4 больше нет.

  • Ключи выдаёт vault.secrets.infrastructure — и сервисам, и самому хранилищу. Хранилище секретов обслуживает все окружения — значит, infrastructure, и защищено не слабее prod (3.2). billing и antifraud получают ключи своих бакетов по путям prod/payments/billing/s3 и prod/risk/antifraud/s3 — управляющий поток infrastructure → prod, разрешённый 3.6.2. Тот же поток идёт и в само S3: Vault создаёт и ротирует ключи в хранилище, иначе «ротация» — это ручная смена пароля раз в год по тикету. Путь секрета несёт окружение и стенд потребителя, и политика Vault сравнивает их с SPIFFE ID клиента.

  • Vault выдаёт ключ, а не открывает канал. Из того, что ключ приходит из infrastructure, не следует, что через infrastructure можно ходить за данными: ключ от prod-бакета выдаётся только клиенту с env/prod в SPIFFE ID. Выдать его стенду другого окружения «на один прогон миграции» — тот самый транзит prod → test через infrastructure, запрещённый 3.2, даже если сам Vault защищён «как prod». Именно поэтому секреты лежат раздельными путями с признаком окружения-источника, а не «в одной папке s3».

Что это даёт на практике

  • Политики из имён. Правило «test не ходит в prod» — одна строка в OPA/Rego, Cilium или конфиге nginx: сравнить {env} клиента и сервера. Без обращения к CMDB в момент решения.

  • Скоуп аудита по построению. Перечень систем в скоупе PCI DSS или 152-ФЗ — это содержимое контура. Не устные объяснения аудитору.

  • Инвентаризация и FinOps без отдельного проекта. Три тега на каждом ресурсе — и вопрос «сколько стоит test у направления payments» превращается в group by.

  • Legacy не трогаем. Переименовывать существующие хосты стандарт не требует: достаточно трёх тегов на уровне платформы виртуализации или облака. Это признаётся полным соответствием.

Чего стандарт EnvSpec Naming не делает

Не описывает процессы согласования доступов. Не задаёт состав политик безопасности. Не требует Service Mesh или конкретного инструмента: SPIFFE ID — это строка, которую собирает ваш PKI и проверяет регулярное выражение. Стандарт фиксирует систему координат, точки входа (шлюзы) и источник идентичности (корпоративный каталог). Остальное — предмет политики организации.

Зачем я это публикую

EnvSpec Naming 1.0.0 — открытый стандарт под лицензией CC BY-SA 4.0: его можно брать целиком во внутренние регламенты. Полный текст — семь разделов, регулярные выражения для линтеров и автоматически проверяемые критерии соответствия — на https://envspec.io.

Мне нужна критика. Конкретно:

  1. Шесть окружений и закрытый список — где это ломается в вашей практике?

  2. «Данные определяют окружение» — есть ли легитимный случай, когда реальные данные вне prod оправданы?

  3. Лимит 13 символов на код контура и системы — терпимо?

  4. Что вы бы выкинули из стандарта как лишнее?

А вы проверили, какие из ваших test-стендов на самом деле prod? 😉