IAM (Identity and Access Management) — это система AWS, которая отвечает на один вопрос: «кто и что может делать». Хотите прочитать файл из хранилища, запустить виртуальную машину, отправить сообщение в очередь — каждый раз AWS сверяется с IAM: а разрешено ли вам это вообще.

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

Пользователи против ролей

Это первое и главное различие, в котором новички путаются.

IAM-пользователь — это постоянная учётная запись. У неё есть имя и пара долгоживущих ключей доступа (access key и secret key) — что-то вроде логина и пароля, только для программ. Эти ключи не меняются сами по себе: создали один раз и пользуетесь, пока не отзовёте.

IAM-роль — это не учётная запись, а набор прав, который можно временно «надеть». Аналогия: пользователь — это ваш постоянный паспорт, а роль — гостевой бейдж на проходной, который выдают на пару часов и который сам по себе ничего не значит без вас. Процесс «надеть роль» называется assume role (принять роль), и в ответ вы получаете не вечные ключи, а временные креды (credentials), которые сами протухают через час-другой.

Ключевое правило, которое стоит запомнить сразу: для программ, серверов и автоматизации используют роли, а не пользователей с ключами.

Почему так:

  • Ключи пользователя живут вечно, поэтому рано или поздно утекают — в код, в логи, в историю команд терминала, в скриншот. И утёкший ключ работает, пока кто-то вручную не спохватится.
  • Креды роли выдаются на минуты-часы и обновляются автоматически. Даже если такой набор утечёт, через час он уже бесполезен.

На практике это выглядит так: ваше приложение крутится на виртуальной машине (EC2), в контейнере (ECS) или в Kubernetes (EKS). Вы привязываете к нему роль — и приложение получает права через неё. В коде и в конфигах нет ни одного ключа. Когда новичок спрашивает «а как моему сервису достучаться до хранилища S3?» — правильный ответ почти всегда «через роль», а не «положи ключи в переменные окружения».

Как устроены политики

Сами по себе права описываются политикой (policy) — это документ в формате JSON, перечисляющий, что можно, а что нельзя. Вот самая простая политика — «разрешить чтение объектов из конкретного бакета (контейнера хранилища) S3»:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::my-bucket/*"
    }
  ]
}

Разберём по полям:

  • Version — версия языка политик. Дата 2012-10-17 не значит, что документ устарел; это просто фиксированный идентификатор актуальной грамматики, его всегда пишут именно так.
  • EffectAllow (разрешить) или Deny (запретить).
  • Action — что именно: s3:GetObject это «скачать объект». У каждого сервиса свой список действий.
  • Resource — над чем: здесь это ARN (Amazon Resource Name, глобальный адрес ресурса) конкретного бакета.

Политики бывают двух видов, и эта пара важна:

  • Identity-based (политика на личности) — привязана к пользователю или роли. Читается как «этой роли можно читать из этого бакета».
  • Resource-based (политика на ресурсе) — привязана к самому ресурсу. Читается наоборот: «этот бакет разрешает доступ такой-то роли или аккаунту». Такие политики нужны, например, чтобы открыть доступ из другого аккаунта или для сервисов вроде S3 и очередей SQS.

Как AWS принимает решение, можно свести к трём правилам:

  1. По умолчанию запрещено всё (это называется implicit deny, неявный запрет). Если ни одна политика явно не разрешила действие — оно запрещено.
  2. Доступ разрешается, только если есть явный Allow. Внутри одного аккаунта хватает Allow в любой из политик — identity- или resource-, неважно в какой. А при доступе между аккаунтами разрешить должны обе стороны: и identity-политика на стороне того, кто обращается, и resource-политика на стороне ресурса.
  3. Явный Deny сильнее любого Allow. Если хоть где-то стоит запрет на это действие — всё, доступа нет, и никакие разрешения это не перебьют.

Дополнительно у каждого правила можно задать блок Condition (условие), который ещё сильнее сужает доступ: «только если запрос пришёл из такой-то сети», «только с подтверждением через MFA (второй фактор)», «только с шифрованием».

Least privilege — минимум прав

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

Самый частый дефект новичка — написать "Action": "*" и "Resource": "*", то есть «можно всё со всем». Так делают «чтобы не возиться» — и именно это потом превращается в инцидент: одна утёкшая такая роль открывает злоумышленнику весь аккаунт.

На практике least privilege — это итеративный процесс, а не разовая настройка:

  1. Начните узко — дайте минимум, который точно нужен.
  2. Запустите, посмотрите, чего не хватает (AWS показывает отказы в логах, а специальные анализаторы доступа подсказывают, какие права реально используются).
  3. Добавьте недостающее. Повторяйте.

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

STS и временные креды

За всеми временными кредами стоит отдельный сервис — STS (Security Token Service, сервис выдачи токенов безопасности). Когда кто-то «принимает роль», под капотом вызывается операция AssumeRole, и STS возвращает короткоживущий набор: access key, secret key и токен сессии. По умолчанию они живут час, максимум можно настроить до 12 часов.

Команда вручную выглядит так:

aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/my-app-role \
  --role-session-name demo-session

Самое полезное для новичка — понять, что на этом механизме построено почти всё:

  • Роль виртуальной машины (instance role) незаметно дёргает STS за вас — SDK сам получает и обновляет креды, вам не надо ничего писать.
  • В Kubernetes (EKS) то же самое делают механизмы IRSA или более новый Pod Identity — они выдают поду временные креды роли.
  • Доступ между аккаунтами — это assume роли в чужом аккаунте.
  • Вход через корпоративную учётку (федерация) — тоже выдача временных креды.

Как только в голове укладывается «креды временные, и берутся они через assume» — большинство вопросов «а откуда сервис вообще берёт доступ без ключей в коде» отпадает само.

Доступ между аккаунтами

В AWS аккаунты — это основная граница изоляции: по умолчанию из одного аккаунта в другой не достучаться никак. Когда такой доступ всё же нужен (например, сервис из аккаунта A должен читать данные в аккаунте B), его делают через роль, а не через общие ключи.

Схема такая:

  1. В аккаунте-владельце ресурса (B) заводят роль.
  2. К роли цепляют trust policy (политику доверия) — она говорит «эту роль разрешено принимать аккаунту A».
  3. К той же роли цепляют identity-политику с нужными правами (например, чтение бакета).
  4. Сервис из аккаунта A вызывает AssumeRole для этой роли, получает временные креды и работает с ними.

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

Где это применяется

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

Где вы столкнётесь с IAM сразу:

  • Любой ваш сервис в облаке (виртуальные машины, бессерверные функции, контейнеры) получает доступ к другим сервисам через роль.
  • Конвейеры доставки кода (CI/CD) тоже работают через роли, а не через зашитые ключи — это разбирается в принципах конвейера доставки.
  • В Kubernetes доступ подов к облачным сервисам настраивается через роли — см. деплой и конфигурацию.

Типичные ошибки новичков, которых стоит избегать с первого дня:

  • Класть долгоживущие ключи пользователя в код или переменные окружения вместо использования роли.
  • Выдавать "*" в Action или Resource «чтобы заработало», а потом забыть сузить.
  • Удивляться, что доступа нет, хотя Allow есть — почти всегда виноват явный Deny где-то выше или забытый implicit deny (нигде не разрешили).
  • Хранить ключи в общем доступе для связи между аккаунтами вместо настройки роли с trust policy.

Что учить дальше: как именно хранят секреты и шифруют данные — в безопасности и наблюдаемости; как роли описываются в инфраструктуре-как-коде, чтобы не кликать в консоли руками — в основах IaC и Terraform; общий взгляд на надёжную архитектуру — в Well-Architected.