Темы



Обмен облачной идентичности на собственную: аттестация рабочих нагрузок на управляемых вычислительных ресурсах

Коротко сгенерировано ИИ по тексту статьи
  • Netflix разработал механизм аттестации заданий Spark на Amazon EMR для обмена облачных ролей IAM на внутренние сертификаты X.509 сервиса Metatron.
  • Драйвер Spark аттестуется через AWS STS и раздает сертификаты тысячам исполнителей по шифрованной RPC-сети, предотвращая превышение лимитов частоты запросов.
  • Роли Проектов данных сопоставляются с ролями IAM в пропорции 1:1 и шардируются по пулу аккаунтов AWS в расчете на десятки тысяч проектов.

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

Автор: Дхрув Пратап (Dhruv Pratap)

Введение

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

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

В этой статье описывается, как мы устраняем этот разрыв для рабочих нагрузок Apache Spark, выполняющихся на Amazon EMR. Рабочая нагрузка, начинающаяся лишь с учетными данными AWS, в итоге должна получить полноценную внутреннюю идентификацию. Сам обмен данными прост. Сделать его надежным — вот что потребовало инженерной проработки. Почти всё из описанного ниже не привязано строго ни к Spark, ни к EMR.

Две системы идентификации

Внутренняя аутентификация между сервисами в Netflix работает на базе закрытой инфраструктуры открытых ключей (PKI) под названием Metatron. Каждая рабочая нагрузка получает недолговечный сертификат X.509, а сервисы аутентифицируют друг друга с помощью взаимного TLS (mTLS). Рабочая нагрузка не может просто так запросить сертификат. Он выдается только после того, как служба идентификации убедится, что запрашивающий действительно является именно той рабочей нагрузкой, за которую себя выдает. Этот шаг проверки называется аттестацией. В каждой поддерживаемой нами среде (виртуальные машины, контейнеры, функции) аттестация опирается на некоторые специфичные для среды доказательства, которые платформа может проверить самостоятельно.

Вторая концепция — это «Проект данных» (Data Project), который является нашей единицей владения данными. Проект данных владеет таблицами, имеет набор авторизованных пользователей и собственную идентичность. Задания выполняются от лица Проекта данных, а не того человека, который их запустил. Именно это обеспечивает согласованность контроля доступа на уровне таблиц и аудита как для запланированных, так и для интерактивных сценариев использования.

Итак, проблема заключается в следующем. Задание Spark на управляемых вычислительных ресурсах запускается с ролью выполнения AWS и без внутренней идентичности. Всё, что ему требуется внутри компании (чтение зашифрованного столбца, оценка списков контроля доступа (ACL) таблиц, удержание интерактивной сессии дольше, чем живет недолговечный токен), требует внутренней идентичности.

Одна идентичность, одна роль

Архитектура опирается на решение, принятое полностью вне стека Spark. Каждая идентичность Проекта данных сопоставляется в пропорции 1:1 с выделенной ролью IAM, а сервис, управляющий метаданными Проекта данных, записывает это сопоставление.

Именно это сопоставление делает трансляцию возможной. Оно позволяет утверждению в терминологии провайдера (»этот процесс запущен с ролью R») превратиться в утверждение в нашей терминологии (»этот процесс является рабочей нагрузкой W»). Без этого не во что переводить, и никакая криптография не поможет. Сложная часть объединения двух систем идентификации редко заключается в самом протоколе. Она заключается в фиксации сопоставления и поддержании его авторитетности.

Сразу возникает практическое возражение. Один аккаунт AWS не может содержать десятки тысяч ролей IAM, а мы ожидаем порядка десятка тысяч проектов данных. Мы решили эту проблему путем детерминированного шардирования ролей проектов данных по небольшому пулу выделенных аккаунтов. Это отлично масштабируется за пределы прогнозируемого количества проектов и имеет полезный побочный эффект: роли рабочих нагрузок остаются по ту сторону границы аккаунта от плоскостей управления (control planes), которые их запускают.

Компоненты

В процессе участвуют пять компонентов.

Плоскость управления (control plane) — это единственный сервис, которому разрешено запускать задания Spark. Он определяет роль IAM Проекта данных, создает и подписывает полезную нагрузку с метаданными рабочей нагрузки, а затем отправляет задание с этой ролью в качестве роли выполнения. Он хранит ключ подписи, выданный ему исключительно для этой цели.

Сервис Проектов данных (Data Project service) является авторитетным источником для сопоставления идентичностей и ролей.

Сервис идентификации (Identity service) принимает запросы на аттестацию, проверяет их и выдает сертификаты.

Плагин Spark предоставляет точку интеграции (хук). Начиная с версии Spark 3.0 появился интерфейс плагинов с компонентами на стороне драйвера и исполнителей (executors), которые инициализируются во время загрузки этих процессов.

AWS STS выступает в роли нотариуса, что не является его обычной задачей.

Шаг первый: плоскость управления создает подписанное утверждение

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

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

Шаг второй: рабочая нагрузка доказывает владение облачной идентичностью

Когда управляемый сервис запускает процесс драйвера, он делает это от имени пользователя ОС, которому доступны учетные данные роли выполнения. Плагин на стороне драйвера инициализируется и использует эти учетные данные для подписания (но не отправки) запроса к эндпоинту идентификации провайдера (sts: GetCallerIdentity). Результатом является недолговечный предварительно подписанный URL-адрес (pre-signed URL).

Этот URL-адрес представляет собой передаваемое доказательство владения. Любой может запросить его. Но получить его мог только обладатель учетных данных роли. При этом ответ поступает от AWS, а не от рабочей нагрузки, и в нем указано, какая роль подписала запрос. Рабочая нагрузка не может солгать об этом ответе, потому что она сама его не предоставляет.

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

Плагин отправляет один запрос на аттестацию, содержащий оба артефакта: предварительно подписанный URL и подписанные метаданные.

Шаг третий: подтверждение (короборация)

Сервис идентификации выполняет четыре действия.

  1. Он запрашивает предварительно подписанный URL в AWS STS и считывает роль, которая его подписала. Это заявление провайдера.
  2. Он проверяет подпись метаданных с помощью ключа, выданного плоскости управления. Это заявление платформы.
  3. Он сопоставляет (короборирует) их оба. Роль, о которой сообщает AWS, должна быть именно той ролью, которую, по заявлению плоскости управления, она задействовала для идентичности, указанной в метаданных.
  4. Он выдает сертификаты для этой идентичности с ограничением по среде, стеку и деталям из подписанных метаданных.

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

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

<

Проблема веерной рассылки (fan-out)

Приложение Spark состоит из одного драйвера и до нескольких тысяч исполнителей (executors), которые создаются и уничтожаются на протяжении всего жизненного цикла задания. Аттестация, спроектированная из расчета на один процесс на хост, этого не выдержит.

Здесь есть два жизнеспособных ответа.

В первом случае каждый исполнитель выполняет аттестацию независимо. Это единообразно, не создает новых границ доверия и обосновывает идентичность каждого процесса тем же самым проверенным провайдером доказательством. Минус — амплификация. Одно крупное задание может сгенерировать тысячи вызовов STS и тысячи запросов на аттестацию в виде всплеска, что очень похоже на атаку и создает жесткую зависимость от лимитов провайдера на частоту запросов.

Во втором случае исполнители наследуют учетные данные от драйвера. Драйвер выполняет аттестацию один раз и распространяет учетные данные среди исполнителей по внутренней RPC-сети Spark, которую мы настраиваем с помощью аутентификации и шифрования AES-GCM, чтобы в этом участвовали только процессы в рамках одного приложения. Нагрузка на сервис идентификации остается постоянной. Минус — появление второй границы доверия и драйвера, который теперь становится точкой распространения учетных данных.

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

Жизненный цикл

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

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

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

Почему этот подход универсален

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

  1. Опирайтесь на один заменяемый примитив. Единственное авторитетное соответствие 1:1 между вашей идентичностью и идентичностью провайдера делает трансляцию возможной. Остальное — техническая реализация.
  2. Требуйте два независимых утверждения и сопоставляйте их. Одно от провайдера — неподделываемое и недостаточно детализированное. Второе от вашей плоскости управления — детализированное и повторяемое. Доверяйте их пересечению и никогда — каждому в отдельности.
  3. Ограничивайте круг лиц, обладающих ключом подписи. Если ровно один сервис может сформировать заявление платформы, ваша история доверия умещается в одно предложение.
  4. Интегрируйтесь на том уровне, который вы все еще контролируете. На управляемых вычислительных ресурсах вы редко контролируете хост или его систему инициализации, но почти всегда контролируете среду выполнения: плагин, агент, точку входа. Аттестация должна происходить именно там.
  5. Примите осознанное решение о политике амплификации. Распределенные движки умножают каждую поцессную операцию на свой уровень параллелизма.
  6. Сделайте аттестацию повторяемой, а учетные данные — недолговечными. Продление — это обязательное требование, а не второстепенная задача.

Что делает результат надежным, так это то, что ни один участник не выдает идентичность в одиночку. Ни рабочая нагрузка, ни плоскость управления, ни провайдер. А рабочая нагрузка, как сторона, находящаяся в наиболее уязвимом для доверия положении, никогда не просит поручиться за себя.

Благодарности

Спасибо Амеру Хессону (Amer Hesson) за абстракцию Проекта данных, Нику Сио (Nick Siow) за шардирование ролей IAM Проектов данных и Дугу Кларку (Doug Clark) за аттестацию Metatron.

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

© Netflix Tech Blog