IAM и наименьшие привилегии в облаке

Почему роль с правами «звёздочка на всё» — это бомба замедленного действия, и как выдавать ровно столько доступа, сколько нужно.

IAM (Identity and Access Management) — система облака, которая решает, кто (пользователь, сервис, роль) и что может делать с какими ресурсами. Политика IAM — это и есть граница ваших привилегий.

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

Зачем это знать защитнику

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

Особое внимание защитник уделяет так называемой эскалации привилегий через IAM. Дело в том, что некоторые права опасны не сами по себе, а тем, что позволяют выдать себе ещё прав. Скромный на вид набор разрешений — право создавать политики и прикреплять их к ролям, право передавать роль (iam:PassRole) сервису, право менять собственную политику — может стать ступенькой к *:*. Поэтому при ревью политик мы смотрим не только «что эта роль может делать с данными», но и «может ли она переписать саму систему доступа». Минимизация прав закрывает этот класс рисков на корню: если роль не умеет управлять IAM, она не сможет и расширить себя.

Роли и политики

Политика описывает разрешения декларативно. Сравните опасную «звёздочку» и узкую политику. Вот over-permissioned вариант, который часто появляется «чтобы просто заработало»:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*"
  }]
}

Защищённая политика разрешает ровно нужное действие на конкретном ресурсе:

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

Дайте сервису роль, а не личный ключ; права прописывайте от задачи (read-only там, где не нужна запись) и опирайтесь на условия (например, ограничение по сети источника или обязательный MFA для чувствительных действий). Полезно мыслить тремя «осями» политики: кто (principal — личность или сервис), что (action — конкретные API-вызовы) и над чем (resource — точные ARN, а не *). Чем уже каждая ось и чем строже условия, тем меньше способов злоупотребить доступом. Условия — недооценённый инструмент: они позволяют сказать «можно, но только из нашей VPC», «можно, но только с MFA не старше часа», «можно читать, но только объекты с определённым тегом» — и тем самым превратить широкое разрешение в узкое, контекстно-зависимое.

Избегаем over-permission

Лишние права накапливаются незаметно: добавили s3:* на отладке и забыли сузить. Боритесь с этим методично:

  • Стартуйте с минимума и расширяйте по необходимости, а не наоборот.
  • Запрещайте wildcard в Action/Resource там, где можно перечислить явно.
  • Используйте управляемые read-only политики для наблюдателей и CI, которым не нужна запись.
  • Разделяйте обязанности: роль деплоя ≠ роль приложения ≠ роль администратора.

Временные креды вместо долгоживущих ключей

Долгоживущие ключи доступа (access key + secret) — это секрет, который легко утекает в репозиторий, лог или образ и живёт годами. Современный подход — временные креды, выдаваемые на минуты-часы через AssumeRole/STS, OIDC-федерацию (например, GitHub Actions без статичных ключей) или привязку роли к ворклоаду (IAM Roles for Service Accounts в Kubernetes, Workload Identity). Иллюстрация запроса временной роли в своей среде:

# Получение временных кредов через роль (учебная среда)
aws sts assume-role \
  --role-arn arn:aws:iam::111122223333:role/app-readonly \
  --role-session-name demo-session

Такие креды автоматически истекают — украденный токен бесполезен уже через час, а статичных ключей в коде просто нет. Особенно показателен случай CI/CD: классическая ошибка — положить долгоживущий ключ в секреты пайплайна, откуда он рано или поздно утекает в лог или в форк. Современная альтернатива — OIDC-федерация: пайплайн предъявляет облаку подписанный токен своей identity, а облако в ответ выдаёт временную роль. Постоянных ключей не существует вовсе, отзывать нечего, а доверие ограничено конкретным репозиторием и веткой. Тот же принцип внутри Kubernetes реализуют IRSA/Workload Identity: под получает креды роли через метаданные, не зная никакого секрета.

Аудит доступа

Наименьшие привилегии нужно проверять. Облачные логи аудита (AWS CloudTrail, GCP Audit Logs, Azure Activity Log) записывают, кто и какой API вызвал. Анализаторы доступа (IAM Access Analyzer) показывают, какие ресурсы доступны извне и какие права реально использовались — это позволяет «обрезать» неиспользуемые разрешения. На что смотреть:

Признаки в логах аудита, требующие внимания:
- использование root-аккаунта для рутинных операций
- массовое чтение/выгрузка из хранилища необычной ролью
- изменение/отключение самих логов аудита (CloudTrail)
- создание новых ключей доступа или ролей вне процесса

Как это работает под капотом

На каждый API-запрос движок IAM собирает все применимые политики (на личности, на ресурсе, границы прав, SCP организации) и вычисляет решение по правилу: явный Deny побеждает всё, иначе нужен хотя бы один Allow, иначе — неявный отказ. Временные креды выдаёт STS: он подписывает короткоживущий токен с зашитой ролью и сроком. Логи аудита — это поток событий, где каждое содержит identity, действие, ресурс и результат; на нём строятся и расследования, и автоматические алерты.

Как защититься

  • Применяй least privilege: минимум прав от задачи, никаких *:*.
  • Давай сервисам роли, а не персональные ключи; разделяй роли по обязанностям.
  • Переходи на временные креды (AssumeRole/STS, OIDC, IRSA) вместо долгоживущих ключей.
  • Включи MFA для людей и условия (сеть/MFA) для чувствительных действий.
  • Веди логи аудита (CloudTrail и аналоги), защищай их от изменения и регулярно «обрезай» неиспользуемые права через Access Analyzer.
  • Не используй root/owner аккаунт для повседневных задач.

Юридическое напоминание: настраивать и аудировать доступ можно только в своих аккаунтах или по письменному поручению владельца. Несанкционированный доступ наказуем (УК РФ ст. 272).

Итоги

  • IAM определяет «радиус поражения»: least privilege ограничивает ущерб от любой компрометации.
  • Wildcard *:* превращает один утёкший токен в захват аккаунта — избегайте его.
  • Временные креды истекают сами и убирают статичные ключи из кода.
  • Аудит (CloudTrail, Access Analyzer) показывает реальное использование и помогает срезать лишние права.
Проверьте себя
1. Что означает принцип наименьших привилегий (least privilege) в облачном IAM?
AДавать каждой роли максимум прав на будущее
BВыдавать ровно те права, что нужны для задачи, и не больше — чтобы ограничить ущерб при компрометации
CОтключить IAM полностью
DИспользовать один общий ключ на все сервисы
2. Чем временные креды (AssumeRole/STS, OIDC, IRSA) лучше долгоживущих access-ключей?
AОни быстрее работают
BОни автоматически истекают и не хранятся статично в коде, поэтому украденный токен быстро становится бесполезным
CОни дают права *:* по умолчанию
DИх нельзя отозвать
3. Какое событие в логах аудита (CloudTrail) — явный повод для тревоги?
AОбычный вход пользователя с MFA
BЧтение публичной документации
CОтключение или изменение самих логов аудита и массовая выгрузка данных необычной ролью
DСоздание задачи в трекере