Основные идеи и конкретная реализация

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

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

Когда мы говорим о ролях и политиках, мы говорим об управлении идентификацией и доступом (IAM). Он составляет основной блок безопасности каждой облачной архитектуры AWS. IAM ограничивает, какой объект может делать что в данной облачной среде. Для этого сообщения в блоге вам необходимо понять две концепции: роли и политики.

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

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

При разработке ролей и политик придерживайтесь принципа наименьших привилегий. То есть разрешать только доступ и действия, которые необходимы службам. Любое расширение сверх этого - потенциальная проблема безопасности. Например, если службе необходимо записывать данные в корзину S3, не следует реализовывать политику, разрешающую все действия S3.

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

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

Вы можете писать сценарии CloudFormation в файлах JSON или YAML. Все примеры здесь и в репозитории кода представляют собой файлы YAML, но вы можете сделать то же самое в JSON.

Вам также доступен набор специальных команд CloudFormation. В следующих примерах я использую три из них:

  1. ! Ref - это внутренняя ссылка; то есть CloudFormation вставляет значение из того же скрипта.
  2. ! Sub используется для замены переменных в строки.
  3. ! GetAtt похож на «! Ref», но указывает на конкретный атрибут ресурса, а не на общую ссылку.

Большая картинка

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

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

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

Детали реализации

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

  1. AssumeRolePolicyDocument определяет, какая служба может взять на себя эту роль. Это описано в разделе документа Принципал (подробности см. Во фрагменте кода ниже). sts в разделе Action - это сокращение от AWS Security Token Service. Эта служба предоставляет временные учетные данные для проверки действия.
  2. ManagedPolicyArns относится к документам политики, связанным с этой ролью. ARN - это имя ресурса Amazon, которое служит идентификатором для ресурсов, созданных на AWS.

Вот как это выглядит в CloudFormation на примере роли CodeBuild:

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

Политики для компонентов разработки

В рабочий процесс разработки вовлечены две службы: CodePipeline и CodeBuild. CodePipeline - это инструмент оркестровки, который запускает проект CodeBuild всякий раз, когда разработчики помещают новую версию основной ветки в репозиторий кода.

Сначала давайте посмотрим на CodePipeline. В нашем сценарии сервис должен взаимодействовать с тремя сервисами:

  • Ему необходимо получать обновления от CodeCommit, чтобы зарегистрировать изменения в главной ветви.
  • В свою очередь, он должен запустить новый запуск связанного проекта CodeBuild.
  • Он должен иметь возможность сохранять и собирать артефакты из S3.

Вот как роль CodePipeline и связанная с ней политика выглядят в CloudFormation:

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

Во-вторых, есть CodeBuild. Он включает четыре разных сервиса.

  • Ему необходимо клонировать репозиторий из CodeCommit.
  • Ему необходимо писать и читать артефакты из S3.
  • Ему необходимо отправить новый образ в реестр эластичных контейнеров (ECR).
  • Ему необходимо записывать данные журнала в CloudWatch.

Последний пункт не обязателен, но я обещаю, что вы пожалеете, если оставите его в стороне. Соответствующие скрипты CloudFormation выглядят так:

Две роли для компонентов разработки не требуют пояснений. Что ж, теперь все становится немного сложнее.

Политики для компонентов пакетного задания

Теперь нам осталось определить роли и политики для пакетного задания. То есть для задачи Fargate и правила CloudWatch, которое ее запускает. Начнем с того, что немного сбивает с толку: задачи Фаргейта.

Хотя одно поле представляет задачу Fargat на архитектурной диаграмме, для него требуются две роли. Подумайте о своих отношениях с начальником. Ваш босс имеет право поручить вам задачу. Вам нужны инструменты для выполнения порученной работы. Это то, что вам нужно и для Fargate. Одна исполнительная роль, также известная как «роль начальника», и роль задачи, также известная как «роль сотрудника».

Роль исполнения включает доступ к двум службам:

  • Ему необходимо получить доступ к изображениям контейнеров в Elastic Container Registry (ECR). В противном случае он не сможет загрузить и запустить образ контейнера пакетного задания.
  • Подобно CodeBuild, ему необходимо записывать информацию журнала в CloudWatch.

Вот как исполняющая роль и ее политика выглядят в CloudFormation:

Жизненно важные политики для роли задачи зависят от того, что разработчики вложили в образ контейнера. То есть, не зная, что реализовали разработчики, нельзя определиться с правильным набором политик. Предположим, что задача загружает некоторые данные из S3, преобразует их и записывает обратно в другую корзину. В этом простом случае вам нужно настроить две службы для роли задачи:

  • Ему необходим доступ к сегментам S3, чтобы получить данные и сохранить выходные данные.
  • Ему необходимо записывать данные журнала в CloudWatch.

Взгляните на спецификацию CloudFormation для получения подробной информации:

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

Наконец, есть правило CloudWatch, которое запускает пакетное задание. Его роль и политика опять же просты и касаются двух сервисов:

  • При необходимости ему необходим доступ к IAM, чтобы передавать роли задачам Fargate.
  • Ему необходим доступ к службе эластичных контейнеров (ECS), которая является службой оркестровки, лежащей в основе Fargate.

Вот спецификация CloudFormation:

Здесь возникает естественный вопрос: почему есть несколько мест, например, для разрешения доступа к журналам CloudWatch? Почему бы не определить одну политику для ведения журнала и не привязать ее ко всем ролям, которым она нужна?

Есть одна основная причина, по которой этого следует избегать: общие политики добавляют зависимости между ресурсами. Эти зависимости могут вернуться, чтобы укусить вас позже. Если вы измените политику, которую принимают на себя несколько ролей, вы можете сломать что-то, даже не осознавая этого.

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

Поделитесь своими мыслями и опытом в комментариях. Я также рад подключиться к Twitter и LinkedIn. Спасибо за чтение!