← назад к разделу

ОБЛАКА IAM

Обязательно

Учётные записи и права в облаке

IAM · Roles · Least privilege

Пользователи для людей, сервисные аккаунты для кода, временные роли и минимум прав как процесс.

1. Человек и программа получают разные идентичности

1 / 5

Пользователь входит через MFA и консоль, сервисный аккаунт получает права через роль workload. Долгий ключ не нужен.

  • Люди имеют персональный доступ.
  • Код получает отдельный principal.
  • Общий admin ключ запрещён.
Human userMFA + consoleService accountworkload identityРазные права и аудит

2. Роль выдаётся на конкретные действия

2 / 5

Политика разрешает только нужные действия на конкретные ресурсы. Нет wildcard на весь аккаунт.

  • Read и write разделяются.
  • Ресурс ограничен именем и условием.
  • Отказ по умолчанию.
Role: orders-writerallow: db:ExecuteQueryresource: orders/*condition: workload = apideny: everything else

3. Роль временная, ключи не лежат в коде

3 / 5

Workload получает короткоживущие credentials через metadata или identity provider. Секреты в git отсутствуют.

  • Credentials истекают.
  • Ротация автоматическая.
  • Кража ограничена временем и правами.
WorkloadAssume roleTemporary credentialsБез долгого ключа в репозитории

4. Минимум прав проверяется эксплуатацией

4 / 5

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

  • Access audit показывает использование.
  • Отдельные роли для producer и consumer.
  • Тест проверяет запрещённое действие.
Actual callsAccess auditSmaller policyLeast privilege подтверждается тестами

5. Утечка имеет план отзыва

5 / 5

Роль отзывается, credentials меняются, журнал показывает действия атакующего. Секреты ротируются регулярно.

  • Отзыв сессии отдельно от кода.
  • Журнал действий включает principal.
  • Обнаружение и отзыв измеряются.
Revoke roleRotate credentialsAudit actionsОграничение последствий утечки

Ключ доступа положили в конфиг «на время отладки», конфиг уехал в git, репозиторий через год стал публичным — и кто-то поднял на ваш счёт сотню машин для майнинга. Это самый частый сценарий взлома облачного аккаунта, и в нём нет ни одной уязвимости в самом облаке: ключ выдали, ключ утёк.

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

учётная запись человек или сервис роль набор разрешённых действий привязка роль на конкретный ресурс действие разрешено или отказ

У всех провайдеров одна модель: сначала облако узнаёт, кто вы, потом ищет привязку роли к ресурсу, и только совпадение обоих даёт действие. Ключ в конфиге ломает первое звено: с ним кто угодно становится вами.

Кто вы: пользователи и сервисные аккаунты

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

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

Что вам можно: роли и привязки

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

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

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

Откуда код берёт права

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

Это объясняет и самый частый отказ новичка: локально код работал от ключа разработчика, в облаке ключа нет, а сервисный аккаунт машине забыли назначить или не выдали ему роль. Ошибка выглядит как «нет прав» или «не удалось найти учётные данные», и лечится не ключом в конфиге, а привязкой роли к сервисному аккаунту машины.

Минимальные права как процесс

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

Дополнительно: при первом чтении можно пропустить

Глубже: как считаются права, когда правил несколькорасширенное

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

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

Глубже: доступ между аккаунтами и вход сотрудниковрасширенное

Крупная компания держит не один аккаунт, а десятки: по команде, по среде, по продукту. Сервису из одного аккаунта иногда нужен ресурс из другого, и для этого не передают ключи: во втором аккаунте заводят роль, которой разрешают доверять сервису из первого, а сервис принимает её на время и получает временные учётные данные. Границы аккаунтов остаются, ключи не расползаются.

Сотрудников в такую компанию заводят не по одному, а через федерацию: облако доверяет корпоративному провайдеру входа, и люди заходят под рабочими учётками, а права получают через группы. Уволился — исчез из корпоративного каталога, и доступ к облаку пропал сам.

Глубже: доступ из конвейера без вечных ключей: федерация по OIDCрасширенное

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

Система сборки (GitHub Actions, GitLab CI и другие) умеет выдавать своему заданию короткоживущий токен OIDC, в котором записано, из какого репозитория, ветки и по какому событию задание запущено. Облако настраивают доверять этому издателю: в AWS это провайдер OIDC в IAM и роль, в политике доверия которой указан репозиторий и ветка; в GCP это Workload Identity Federation с пулом и провайдером, привязанным к сервисному аккаунту; в Azure это федеративные учётные данные у приложения или управляемого удостоверения. Задание предъявляет токен, облако проверяет подпись и условия и выдаёт временные учётные данные на минуты. В репозитории при этом нет ни одного секрета облака: только идентификаторы, которые секретами не являются.

Что здесь ломают. Условие доверия слишком широкое: repo:org/* вместо конкретного репозитория и ветки, и любой репозиторий организации, включая форк с чужим кодом в pull request, получает права на прод. Правило: отдельная роль на репозиторий и на окружение, прод только с ветки main и только по событию выката. Права роли такие же узкие, как у сервисного аккаунта приложения: конвейеру, который выкатывает контейнер, нужны реестр и служба запуска, а не администратор проекта. И журнал: каждое действие конвейера в облаке записано с идентификатором задания, по которому видно, чей коммит это сделал.

Там, где федерации нет (старая система сборки, свой сервер), ключ остаётся, но с сроком жизни в дни, ротацией по расписанию и правами на одну операцию; и это временное состояние с датой, а не архитектура.

Коротко

  • Людям заводят пользователей, программам — сервисные аккаунты; ключи доступа человека в коде программы — ошибка.
  • Права выдают не «пользователю вообще», а связкой: кому, какую роль, на какой ресурс или группу ресурсов.
  • Роль — именованный набор разрешений; узкая роль на один ресурс лучше широкой на весь проект.
  • Код на машинах провайдера получает права без ключей: платформа выдаёт машине или контейнеру временный токен сервисного аккаунта, а библиотека находит его сама.
  • Постоянный ключ выдают только тому, что живёт вне облака: CI-серверу или локальной разработке, и с сроком жизни.
  • Минимальные права — не лозунг, а процесс: начали узко, посмотрели отказы, добавили ровно недостающее.
  • Конвейеру вечный ключ не нужен: он предъявляет облаку токен OIDC своей системы сборки, а облако выдаёт временные права роли с условием на репозиторий и ветку; широкое условие доверия это дыра на весь прод.

Что почитать дальше