open atlas
↑ К треку
Безопасность облака и инфраструктуры CLOUD · 01 · 01

Модель облачной идентичности

Облачная авторизация — не один ACL, а несколько политик, вычисляемых вместе: запрос разрешён, только если какая-то явно разрешает и ни одна не запрещает. Разберись с принципалом, типами политик и порядком deny-by-default — и загадки доступа исчезают.

CLOUD Middle ◷ 15 min
Уровень
ОсновыJuniorMiddleSenior

Ваш сервис читает бакет, к которому ему никогда не выдавали доступ. Вы смотрите в политику роли — про этот бакет ни слова. Смотрите в политику бакета — она разрешает доступ совсем другому аккаунту. И всё же aws s3 ls работает. Никто не ошибся в очевидном файле, потому что облачная авторизация никогда не решается одним файлом. Решение — это слияние нескольких документов: identity-политики вызывающего, политики самого ресурса, общеаккаунтного ограничителя, может быть, permission boundary, — вычисляемых по фиксированным правилам. Бакет читался, потому что его resource-политика выдала доступ вашей роли, а у роли не было deny, чтобы это перебить. Пока вы не сможете прокрутить это слияние в голове, каждый сюрприз с облачным доступом выглядит как магия.

К концу урока вы сможете назвать, кто такой принципал, перечислить типы политик, которые крепятся к идентичностям и к ресурсам, и провести запрос на авторизацию через точное deny-by-default вычисление, которое запускают облачные платформы.

Принципал: кто спрашивает

Каждое решение об авторизации начинается с принципала — сущности, делающей запрос. В облачной IAM-модели принципал почти никогда не человек, набирающий пароль. Это идентичность, которая уже прошла аутентификацию и теперь несёт набор короткоживущих учёток: IAM-роль, принятая EC2-инстансом; Kubernetes service account, обменянный на облачный токен через workload identity; CI-задача, федерировавшаяся по OIDC-токену; execution-роль Lambda. Логин уже состоялся; к моменту вычисления политики платформа знает, какой принципал спрашивает. IAM — это слой авторизации, а не аутентификации: он отвечает на вопрос «можно ли этому уже-известному принципалу выполнить это действие над этим ресурсом», и именно с этого различия начинается бо́льшая часть путаницы.

Это важно по зрелой причине: принципалы обычно машины, и они долгоживущие по замыслу, но короткоживущие по учётке. У роли нет пароля; принципал принимает её и получает учётки, истекающие через час. Поэтому интересная поверхность атаки — не «угадать пароль», а «кому разрешено стать этим принципалом», и это управляется отдельной политикой, к которой мы перейдём.

Два вопроса политики: identity против resource

Облачная платформа задаёт один и тот же запрос с двух сторон, и обе должны согласиться.

  • Identity-политика крепится к принципалу (роли, пользователю, группе). Она говорит, что может этот принципал: «роль report-writer может s3:PutObject в reports-bucket». Читайте как предложение, начинающееся с актора.
  • Resource-политика крепится к самому ресурсу (S3-бакету, SQS-очереди, KMS-ключу). Она говорит, кто может действовать над этим ресурсом: «этот бакет разрешает arn:aws:iam::111:role/report-writer читать». Читайте как предложение, начинающееся с объекта.

Один и тот же доступ можно выразить с любой из сторон, и именно комбинация делает межаккаунтный доступ работающим без правки ролей в чужом аккаунте. Если у бакета аккаунта A есть resource-политика, называющая роль аккаунта B, а у роли B есть identity-политика, разрешающая действие, запрос проходит — в одиночку ни одна сторона не смогла бы выдать его через границу аккаунтов. Это же — самый частый источник «почему оно это читает?»: грант живёт на ресурсе, а не на идентичности, поэтому чтение только политики роли никогда этого не объяснит.

Тип политикиКрепится кОтвечает наТипичное применение
Identity-basedРоль / пользователь / группаЧто может этот принципал?Выдать приложению его права
Resource-basedБакет / очередь / ключКто может действовать над ресурсом?Межаккаунтный доступ
Trust-политикаРоль (дверь AssumeRole)Кто может стать принципалом?Федерация, цепочки ролей
Permission boundary / SCPИдентичность / весь аккаунтКаков потолок, независимо от грантов?Организационные ограничители

Trust-политика: кто может стать этим принципалом

У роли есть дверь, и trust-политика — это замок на ней. Это resource-политика, живущая на роли и отвечающая на вопрос, которого identity-политика вообще не касается: кому в принципе разрешено принять эту роль? Identity-политика говорит, что роль может, когда вы уже внутри; trust-политика говорит, можете ли вы войти.

Это разделение — весь движок облачной федерации. Задача GitHub Actions, предъявляющая OIDC-токен, может стать deploy-ролью только потому, что trust-политика этой роли говорит: «принципалы, федерированные от этого OIDC-провайдера, с этим claim sub, могут меня принять». Человек из вашего SSO-каталога становится admin-ролью, потому что trust-политика доверяет провайдеру идентичности. Ошибитесь в trust-политике — доверьте * или OIDC sub с небрежным wildcard вроде repo:org/* — и вы отдали роль всему интернету, как бы туго ни была закручена её identity-политика. Trust-политика — это та часть, о существовании которой джуны забывают, а сеньоры ревьюят первой, потому что это и есть настоящая граница аутентификации для машинного принципала.

Почему это работает

Почему две отдельные политики на одной роли, а не один объединённый список прав? Потому что «кому можно пользоваться этой возможностью» и «что эта возможность может делать» меняются независимо и принадлежат разным людям. Платформенная команда курирует trust-политику (какие OIDC-провайдеры, какие аккаунты, какие SSO-группы могут принять роль); прикладная команда курирует identity-политику (какие API-вызовы нужны приложению). Слияние заставило бы каждое изменение прав заново открывать границу федерации, а каждое изменение федерации — заново аудитить права приложения. Отделить дверь от комнаты — это least privilege, применённый к самой структуре.

Как решение вычисляется на самом деле

Вот правило, которое растворяет загадки. Облачная авторизация — deny by default, и вычисление — это не «найти подходящий allow», а фиксированный приоритет:

  1. Старт — неявный deny. Ни одно утверждение не подходит → запрос отклонён. Ничего не разрешено, пока что-то не выдаст грант.
  2. Явный Deny всегда побеждает. Если любая применимая политика — identity, resource, boundary или организационный ограничитель — содержит подходящий Deny, запрос отклонён, точка. Никакой allow его не перебьёт.
  3. Явный Allow снимает неявный deny — но только в пределах потолка. Permission boundary или организационный ограничитель (SCP) могут урезать достижимое, даже когда identity-политика говорит Allow; эффективное право — это пересечение выданного и того, что разрешает потолок.

Так что реальное вычисление таково: deny, пока (какая-то политика разрешает) И (ни одна не запрещает) И (грант внутри каждого применимого потолка). Этот порядок объясняет, почему чрезмерно широкий Allow * гораздо менее опасен, чем боятся, когда его ограничивает boundary, — и почему один залётный Deny способен сломать деплой, у которого «очевидно есть права».

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

Прокрутим стартовую загадку через модель. Ваша роль в аккаунте B может s3:ListBucket на бакете в аккаунте A. Проследим:

  • Trust-политика роли B разрешает вашему EC2-инстансу / CI-задаче принять её. Аутентификация машинного принципала: готово.
  • Identity-политика роли B разрешает s3:ListBucket на arn:...:bucket-in-A. Сторона гранта со стороны B: есть.
  • Resource-политика бакета A разрешает arn:aws:iam::B:role/yours делать s3:ListBucket. Сторона гранта со стороны A: есть.
  • Нигде нет Deny, и действие лежит внутри permission boundary роли B и организационных ограничителей A.

Обе стороны согласились, ни один deny не вмешался, потолок разрешил → разрешено. Причина, по которой чтение одной роли не сработало, в том, что половина гранта жила на ресурсе в другом аккаунте. Зрелая привычка — для любого неожиданного доступа спросить: «покажите мне каждую политику в слиянии — обе идентичности, оба ресурса, boundary, организационный ограничитель, — а не только ту, которую я ожидал».

Выбери лучший вариант

GitHub Actions-воркфлоу должен деплоить в ваш облачный аккаунт. Вы хотите, чтобы CI принимал deploy-роль. Какой подход — корректная модель идентичности?

Викторина

Identity-политика на роли говорит `Allow s3:*`, но permission boundary на той же роли разрешает только `s3:GetObject`. Принципал вызывает `s3:DeleteObject`. Что произойдёт?

Викторина

Бакет в аккаунте A читается ролью в аккаунте B, но identity-политики A никогда не упоминают B. Где живёт грант и почему чтение роли B его не объяснило?

Расставь шаги по порядку

Упорядочьте шаги вычисления решения об облачной авторизации, от старта до вердикта:

  1. 1 Старт с неявного deny (по умолчанию ничего не разрешено)
  2. 2 Проверить каждую применимую политику на явный Deny — если хоть один подходит, отклонить безусловно
  3. 3 Искать явный Allow в identity- или resource-политике
  4. 4 Подтвердить, что грант лежит внутри потолка permission boundary / организационного ограничителя
  5. 5 Разрешить только если allowed, не denied и внутри потолка
Вспомните перед уходом
  1. 01
    Различите identity-политику принципала, resource-политику и trust-политику. На какой вопрос отвечает каждая и почему они разделены?
  2. 02
    Пройдите через то, как облачная платформа вычисляет запрос на авторизацию, включая роль permission boundary.
Итог

Облачный IAM никогда не решает доступ по одному файлу. Принципал — это уже-аутентифицированная идентичность, почти всегда машина с короткоживущими принятыми учётками, а не человек с паролем. Сливаются три вопроса политики: identity-политика говорит, что может принципал, resource-политика говорит, кто может действовать над ресурсом (механизм межаккаунтных грантов), а trust-политика на роли говорит, кому вообще можно стать этим принципалом — реальная граница аутентификации и то, что сеньоры ревьюят первым, потому что wildcard там раздаёт роль всем. Вычисление — deny-by-default с фиксированным приоритетом: любой явный Deny побеждает, явный Allow снимает неявный deny, но только внутри потолка permission boundary или организационного ограничителя, поэтому эффективное право — пересечение гранта и потолка. В следующий раз, когда доступ вас удивит, не читайте одну политику — прокрутите всё слияние: обе идентичности, оба ресурса, trust-дверь и каждый потолок.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 7 завершено
Связанные уроки
углубляется в

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources2
expand
  1. 01
  2. 02

Trademarks belong to their respective owners. Editorial reference only.