Контейнеризация, CI/CD, оркестрация, микросервисы и agile-процессы – это облако тегов, которое теперь находится в словаре security-инженеров. Микросервисная модель и сопутствующие технологии привели к многообразию подходов в реализации архитектуры безопасности современных решений, и единого подхода к ее построению пока еще не видно. Зато есть технологические лидеры в области микросервисной разработки, есть известные недостатки конфигурации и уязвимости в реализации разных архитектурных подходов, и есть огромное количество «лучших практик» для построения надежной архитектуры. В данном материале, подготовленном на основе исследовательской статьи, опубликованной совместно с Денисом Макрушиным (makrushin) из команды Advanced Security Research исследовательской лаборатории Huawei Advanced Software Technology Lab, мы разберем типовые архитектурные подходы к реализации аутентификации и авторизации в микросервисных системах, их преимущества и недостатки. И сделаем это для того, чтобы у архитекторов безопасности была возможность сфокусироваться на реализации требуемой модели, а не на многочасовых поисках нужной информации. Архитектура микросервисов все чаще используется для проектирования и внедрения прикладных систем как в облачных, так и в локальных инфраструктурах, крупномасштабных приложениях и сервисах. Достаточно изучить Хабр на предмет различных практик, связанных с разработкой распределенных и отказоустойчивых систем, чтобы убедиться в повсеместном внедрении микросервисной модели. На этапах разработки и внедрения программного продукта необходимо решить множество проблем безопасности. Основополагающими требованиями, над которыми ломает голову aрхитектор безопасности (Application Security Architect – роль в крупной продуктовой компании, которая еще не избавляет от технических задач Security Engineer'a, но которая уже добавляет высокоуровневые проблемы, связанные с архитектурой и процессами) и которые должны быть решены на этапе проектирования, являются аутентификация и авторизация (для краткости, АА). Поэтому архитекторам безопасности приложений крайне важно понимать и правильно использовать существующие архитектурные шаблоны для реализации АА в системах, основанных на микросервисах. Цель нашего исследования заключалась в том, чтобы выявить такие шаблоны и дать архитектору безопасности рекомендации по их возможному использованию. Исследование проводится с учетом трех ключевых вопросов: В ходе исследования мы провели обзор основных электронных библиотек научных статей, мы также просмотрели стандарты безопасности, презентации на крупных конференциях по безопасности и локальных тематических митапах (привет, OWASP Moscow Meetup). Итогом стали следующие результаты: Мы провели декомпозицию функций АА (если собираешься стать архитектором безопасности приложений, то добавляй сложные слова и термины в свою коллекцию – возможно, они пригодятся на совещаниях) на основе характеристик типовых микросервисных приложений и определили следующий список подфункций безопасности (Рисунок 1): пограничная авторизация (edge-level authorization), авторизация на уровне сервиса (service-level authorization), пробрасывание идентификатора внешнего субъекта (external entity identity propagation), межсервисная аутентификация (service-to-service authentication). Затем мы рассмотрели основные электронные базы данных и библиотеки, а также стандарты безопасности и презентации на основных конференциях по безопасности с целью выявления существующих архитектурных схем.

Рисунок 1. Подфункции аутентификации и авторизации в системах на базе микросервисов Разберем основные модели и их схемы. В простом сценарии авторизация может происходить только на пограничном уровне (при помощи шлюза API). Шлюз API можно использовать в качестве центра авторизации для всех последующих микросервисов, исключая необходимость обеспечения аутентификации и контроля доступа для каждого отдельного микросервиса. В этом случае NIST рекомендует применять смягчающие меры контроля, такие как межсетевое экранирование и взаимная аутентификация, для предотвращения прямых анонимных подключений к внутренним службам в обход шлюза API. Однако авторизация на пограничном уровне имеет следующие недостатки: В большинстве случаев команды разработчиков реализуют авторизацию в обоих местах: в API шлюзе и на уровне микросервисов. Для аутентификации внешних субъектов можно использовать токены доступа, к примеру (reference-токен или автономный (self-contained) токен, передаваемые через заголовки HTTP (например, "Cookie" или "Authorization"), или же использовать mTLS. Для дальнейшего обсуждения мы используем термины и определения (рисунок 2), позаимствованные у NIST. Функциональные компоненты системы контроля доступа можно классифицировать следующим образом: Авторизация на уровне сервиса дает каждому микросервису больше контроля для реализации политик доступа. На основе анализа докладов, представленных на ведущих конференциях по безопасности, мы определили следующие подходы к реализации авторизации на уровне сервисов: В этом шаблоне команда разработчиков реализует PDP и PEP непосредственно на уровне кода микросервиса (рис. 3). Все правила контроля доступа, а также атрибуты, необходимые для реализации этого правила, определяются и хранятся в каждом микросервисе (шаг 1). Когда микросервис получает (шаг 2) запрос на доступ вместе с некоторыми метаданными авторизации (например, контекст конечного пользователя), микросервис анализирует его (шаг 3) для того, чтобы сгенерировать решение политики контроля доступа, а затем реализует (enforce) авторизацию (шаг 4).

Рисунок 3. Высокоуровневая архитектура децентрализованного шаблона Существующие библиотеки и фреймворки для различных языков программирования позволяют разработчикам осуществлять авторизацию на уровне микросервисов. Реализация авторизации на уровне исходного кода означает, что код должен обновляться всякий раз, когда команда разработчиков хочет изменить логику авторизации.  Соответственно, данная модель несет в себе следующие ограничения: С другой стороны, внедрение политики контроля доступа в код микросервиса позволяет разработчикам использовать более гибкие правила контроля доступа, поскольку микросервис обладает всеми необходимыми данными доменной модели. В этой модели правила контроля доступа определяются, хранятся и оцениваются централизованно (рисунок 4). Правила контроля доступа определяются с помощью PAP (шаг 1) и доставляются в централизованную PDP вместе с атрибутами субъектов и объектов доступа, которые необходимы для использования этих правил (шаг 2). Когда субъект вызывает микросервис (шаг 3), код микросервиса вызывает централизованный PDP через сетевой вызов, а PDP генерирует решение политики контроля доступа, оценивая входной запрос по правилам и атрибутам контроля доступа (шаг 4). На основе решения PDP микросервис реализует авторизацию (шаг 5). 
Рисунок 4. Высокоуровневая архитектура централизованного шаблона с единой PDP Некоторыми преимуществами этой схемы являются: Для определения правил контроля доступа команда разработчиков и DevOps-инженеров должна использовать язык или нотацию. Примером может служить язык разметки Extensible Access Control Markup Language (XACML) и Next Generation Access Control (NGAC), который является стандартом для реализации описания правил политики. Следует отметить, что применение XACML не всегда является удачной стратегий, так как требует изучения отдельного, сложного синтаксиса, что может привести к увеличению объема работы для разработчиков и DevOps-инженеров. Этот шаблон плохо влияет на время обслуживания запросов из-за дополнительных сетевых вызовов PDP; использование кэширования решений политики авторизации на стороне микросервиса позволяет уменьшить сетевые задержки. Следует отметить, что PDP должен работать в режиме высокой доступности из-за возможных проблем с отказоустойчивостью. Архитекторы безопасности приложений должны комбинировать его с другими шаблонами (например, авторизация на уровне шлюза API), чтобы избежать наличия единой точки принятия решений и обеспечить соблюдение принципа "эшелонированной обороны". В этой модели правила контроля доступа определяются централизованно, но хранятся и оцениваются на уровне микросервисов (рисунок 5). Правила контроля доступа определяются с помощью PAP (шаг 1) и доставляются во встроенную PDP вместе с атрибутами субъектов и объектов доступа, которые необходимы для использования этих правил (шаг 2). Когда субъект вызывает микросервиса (шаг 3), код микросервиса вызывает PDP, а PDP генерирует решение политики контроля доступа, оценивая входной запрос по правилам и атрибутам контроля доступа (шаг 4). На основе решения PDP микросервис применяет авторизацию (шаг 5).

Рисунок 5 Высокоуровневая архитектура централизованной модели со встроенной PDP PDP код в этом случае может быть реализован как встроенная библиотека микросервиса или «sidecar-прокси». Sidecar обрабатывают коммуникации между сервисами, производят мониторинг и устраняют проблемы безопасности, то есть все, что может быть абстрагировано от отдельных сервисов, подробнее можно почитать тут. В связи с возможными отказами сети или хоста и задержками в сети рекомендуется реализовать встроенную PDP в виде микросервисной встроенной библиотеки или sidecar на одном хосте с микросервисом. Встроенная PDP обычно хранит политику авторизации и связанные с политикой данные в памяти, чтобы уменьшить количество внешних зависимостей во время авторизации и для получения низкой задержки. Основное отличие от "централизованного шаблона с единой точкой принятия решения" с подходом к кэшированию заключается в том, что решения по авторизации не хранятся на стороне микросервиса, вместо этого на стороне микросервиса хранится актуальная политика авторизации. Также кэширование решений по авторизации может привести к применению устаревших правил авторизации и нарушениям правил контроля доступа. В выступлении “How Netflix Is Solving Authorization Across Their Cloud” представлен практический пример применения шаблона "Централизованную модель со встроенной PDP" для реализации авторизации на уровне микросервисов (рисунок 6): Преимущества этих шаблонов такие же, как и для "Централизованных шаблонов с одним PDP". Кроме того, шаблон не сильно влияет на задержки в обслуживании сетевых запросов из-за встраивания PDP на уровне микросервисов. Существует несколько проблем, которые необходимо учитывать при применении этой модели: Существует два общих способа реализации межсервисной аутентификации: В подходе mTLS каждый микросервис может уверенно определить, с кем он общается, в дополнение к достижению конфиденциальности и целостности передаваемых данных. Каждый микросервис при старте должен получать свою пару открытый/закрытый ключей и открытый ключ доверенного центра сертификации, которые в дальнейшем используются для аутентификации микросервиса получателя через mTLS. mTLS обычно реализуется с самохостинговой инфраструктурой открытых ключей. Основными проблемами при использовании mTLS являются обеспечение доступа к ключам и первичная загрузка ключей, отзыв сертификатов и ротация ключей. Подход на основе токенов работает на прикладном уровне. Токен является контейнером и может содержать идентификатор вызывающего микросервиса (microservice id) и его разрешения (scopes). Вызвающий микросервис может получить токен, обращаясь к специальной службе токенов безопасности, используя свой собственный идентификатор и пароль, а затем присоединяя его к каждому исходящему запросу, например, через HTTP заголовки. В большинстве случаев аутентификация на основе токенов работает с использованием протокола TLS, что дополнительно обеспечивает конфиденциальность и целостность передаваемых данных. Согласно ряду научных публикаций (например, Overcoming Security Challenges in Microservice Architectures) и нескольким докладам на ведущих конференциях по безопасности (например, A Pragmatic Approach for Internal Security Partnerships), mTLS является наиболее популярным вариантом аутентификации микросервисов. Модель сетевой сегментации или межсетевой защиты не обеспечивает должного уровня безопасности при передаче данных между сервисами, и в настоящее время крайне редко используется на практике в виде единственного механизма защиты. Задача данного исследования и подготовленного обзора заключается в том, чтобы предоставить Архитектору безопасности лучшие практики для реализации модели АА в разрабатываемом продукте и оставить его наедине с вопросом: «Что из этого лучше подходит к моему приложению?». Используя преимущества и недостатки, отмеченные в этом материалы, Архитектор, может аргументировать свой выбор и разработать стратегию для реализации АА в рамках своего продукта. При этом, мы не исключаем, что на этот же вопрос «Что из этого лучше подходит к моему приложению?» Архитектор ответит: «Кажется, что ничего не подходит. Придется делать свою модель с блэк-джеком». И в итоге, разработанная им модель окажется в данном списке в качестве новой «best practice» — смело делай pull requests в соответствующую шпаргалку от OWASP. В полном тексте научной публикации, помимо рекомендаций архитектору по безопасности приложений по выбору подходящего архитектурного шаблона, можно найти полный перечень источников информации (публикации, выступления на конференциях), которые были проанализированы в рамках данного исследования. AppSec Architect, Advanced Software Tech Lab