Аутентификация сервис-сервис
Урок о том, почему «мы же внутри одной сети» — опасное оправдание, и как сервисы должны доказывать друг другу, кто они.
Zero-trust — модель, в которой ни один запрос не считается доверенным по факту своего происхождения; доверие каждый раз заново подтверждается проверяемой личностью и правами, независимо от того, из какой сети пришёл вызов.
В монолите вызов одной функции другой бесплатен и доверен. В микросервисах тот же вызов превращается в сетевой запрос между процессами, который теоретически может сделать кто угодно, кто оказался в той же сети. Если сервис заказов слепо верит любому, кто постучался на его внутренний порт, то злоумышленник, пробравшийся в одну часть инфраструктуры, получает ключи от всего.
Зачем это знать защитнику
Старая модель «жёсткий периметр, мягкая середина» (защищаем границу, а внутри всё доверяем) раз за разом проваливается: достаточно одной уязвимости на периметре или одного скомпрометированного контейнера, чтобы атакующий начал свободно ходить между сервисами (lateral movement). Аутентификация сервис-сервис превращает мягкую середину в систему, где каждый шаг приходится подтверждать.
Почему внутренняя сеть — не доверие
«Внутренняя сеть» в облаке — понятие подвижное: контейнеры создаются и удаляются, IP переиспользуются, сервисы соседствуют с чужими нагрузками. IP-адрес или нахождение в одном VPC не доказывают личность — их можно подделать или унаследовать после компрометации соседа. Поэтому решение принимается не по адресу источника, а по криптографически проверяемому удостоверению самого сервиса.
Mutual TLS (mTLS)
Обычный TLS проверяет только сервер: клиент убеждается, что говорит с настоящим банком. В mTLS проверка взаимная — и клиент, и сервер предъявляют сертификаты, подписанные общим доверенным центром (внутренним CA). Так каждый сервис получает проверяемую личность на уровне транспорта:
Сервис A --- предъявляет свой сертификат ---> Сервис B
Сервис A <-- предъявляет свой сертификат --- Сервис B
Оба проверяют: подпись сертификата сделана нашим внутренним CA,
сертификат не истёк и не отозван, имя (SPIFFE ID / SAN) ожидаемое.
Принцип конфигурации сервера — требовать клиентский сертификат и валидировать его против доверенного CA:
# Иллюстрация настройки (сервисная сетка / прокси), не для копипаста на бой
mtls:
mode: STRICT # plaintext-подключения запрещены
client_cert: required # клиент обязан предъявить сертификат
ca_bundle: /etc/certs/internal-ca.pem
verify: [signature, expiry, revocation]
В реальности mTLS обычно не пишут руками в каждом сервисе, а делегируют сервисной сетке (service mesh) — sidecar-прокси берёт на себя выдачу, проверку и ротацию сертификатов, прозрачно для кода. Стандарт SPIFFE/SPIRE задаёт, как именно сервису присваивается и подтверждается его идентичность.
Токены сервисов
mTLS отвечает на вопрос «кто звонит» на уровне соединения. Часто нужен ещё уровень приложения — что этому сервису разрешено. Здесь применяют сервисные токены: короткоживущие, подписанные удостоверения с ограниченным набором прав (scope). Сервис получает токен у доверенного эмитента и предъявляет его в запросе; получатель проверяет подпись и scope:
Authorization: Bearer <подписанный токен>
payload (читаемый, не секретный):
sub: "service/billing"
aud: "service/orders" # для кого выписан
scope: "orders:read" # только чтение заказов
exp: "+5min" # живёт минуты, не дни
Важно: токен ограничивает аудиторию (aud) — токен, выписанный для сервиса заказов, нельзя предъявить платёжному сервису. Это снижает урон при утечке.
Как это работает под капотом
В основе и mTLS, и токенов лежит асимметричная криптография: приватный ключ остаётся у владельца, публичная часть (сертификат/ключ проверки) распространяется. Получатель проверяет подпись, не зная секрета отправителя. Доверие иерархично: всё сводится к доверенному корню (внутренний CA или эмитент токенов), которому стороны договорились верить.
Отдельная важная деталь — ротация. Чем дольше живёт ключ или сертификат, тем дороже его утечка. Современный подход — делать удостоверения короткоживущими (часы для сертификатов, минуты для токенов) и автоматически их обновлять. Тогда даже украденный сертификат быстро становится бесполезным, а аварийный отзыв (revocation) и плановая смена компрометированного корня становятся рутинной операцией, а не катастрофой.
Как защититься
- Исходите из zero-trust: каждый межсервисный вызов аутентифицирован и авторизован, независимо от сети.
- Включайте mTLS в режиме STRICT — plaintext-подключения между сервисами запрещены.
- Выдавайте сервисам проверяемую идентичность (SPIFFE/service mesh), а не доверяйте по IP или хедеру.
- Используйте короткоживущие сертификаты и токены с узким scope и явной аудиторией (
aud); настройте автоматическую ротацию и отзыв. - Применяйте наименьшие привилегии: сервису доступны только те эндпоинты соседей, которые ему реально нужны.
- Логируйте, какой сервис к какому обращался — это даёт видимость и помогает заметить аномалии.
Экспериментируйте на своих кластерах и в учебных лабораториях; вмешательство в чужую инфраструктуру наказуемо (в РФ — ст. 272/274 УК РФ).
Итоги
- Нахождение в одной сети не доказывает личность — доверие подтверждается криптографией каждый раз.
- mTLS даёт взаимную проверку сервисов на транспорте; токены сервисов добавляют ограниченные права на уровне приложения.
- Короткоживущие удостоверения и автоматическая ротация резко снижают цену утечки.
- Zero-trust между сервисами останавливает свободное перемещение атакующего внутри инфраструктуры.