Cloud IAM — это система Google Cloud, которая отвечает на один вопрос: «кто и что может делать». Хотите прочитать файл из хранилища, запустить машину, отправить сообщение в тему — каждый раз GCP сверяется: а разрешено ли вам это.
Звучит как скучная бюрократия, но именно тут происходит большинство аварий в облаке. Чаще всего ломают не сложным взломом, а потому что кому-то выдали слишком много прав или JSON-ключ сервисного аккаунта попал в открытый репозиторий. Полчаса на понимание IAM выгоднее, чем потом разбирать инцидент.
Внутри облака ключей не бывает: к машине или поду привязан сервисный аккаунт, и код берёт временный токен у сервера метаданных, а библиотеки Google делают это сами. Снаружи ту же роль играет федерация удостоверений, и JSON-ключ остаётся для упрямого случая с датой пересмотра.
Пользователи против сервисных аккаунтов
Первое различие, в котором путаются новички, — кому вообще выдают доступ.
Пользователь — это человек: аккаунт Google или корпоративная учётка через federation. Люди заходят в консоль, что-то настраивают, смотрят.
Сервисный аккаунт (service account) — учётная запись для программ и виртуальных машин, а не для человека. Её задача — дать доступ вашему коду. Аналог роли, которую «надевает» сервис, в AWS.
Ключевое правило: для программ, серверов и автоматизации используют сервисные аккаунты, а не личные учётки.
Служебная учётная запись — это и личность, и ресурс
Особенность GCP, из которой растёт половина рабочих приёмов: служебная учётная запись существует в двух ролях одновременно.
Как личность — ей выдают права на ресурсы: «этой учётной записи можно читать из хранилища».
Как ресурс — права выдают на неё саму: «этому человеку можно пользоваться этой учётной записью». И вот вторая половина обычно и остаётся незамеченной.
Отсюда два ключевых механизма.
Работа от имени учётной записи (impersonation). Человек или другая учётная запись может получить временный токен служебной учётной записи и выполнять действия от её имени — без всяких ключей:
gcloud storage ls gs://orders-reports \
--impersonate-service-account=orders-app@acme-prod.iam.gserviceaccount.com
Для этого нужна роль создателя токенов (roles/iam.serviceAccountTokenCreator) на эту учётную запись. Это и есть правильный ответ на вопрос «как локально отладить код, который в облаке работает от служебной учётной записи»: вы работаете с теми же правами, ничего не скачивая и не храня. Ключ не создаётся вовсе.
Право «пользоваться» учётной записью (roles/iam.serviceAccountUser). Оно нужно, чтобы присоединить учётную запись к ресурсу — к машине, к сервису, к задаче. И здесь прячется путь повышения прав, о котором стоит знать: человек с этим правом может создать машину с мощной служебной учётной записью и выполнить на ней свой код — то есть получить её права, не имея их напрямую.
Практические выводы: право «пользоваться» выдают узко (на конкретную учётную запись, а не на проект), мощные учётные записи не держат в проектах, где у многих есть право создавать ресурсы, и предпочитают работу от имени — она оставляет след в журнале аудита с указанием, кто именно действовал от имени учётной записи.
Права выдают группам
То же правило, что и в любом облаке, и в GCP оно особенно заметно, потому что привязок много: роли выдают группам, а не людям поимённо.
gcloud projects add-iam-policy-binding acme-orders-prod \
--member="group:orders-developers@acme.com" --role="roles/run.developer"
Что это даёт: приём сотрудника — добавить в группу, уход — убрать; список прав человека виден как список его групп; привязок в политике проекта в разы меньше, и её вообще можно читать глазами.
Как раскладывают группы: по команде и среде (orders-dev, orders-prod с разными ролями), отдельно дежурные, отдельно читатели. Поимённые привязки остаются только как обоснованные исключения — и их видно в политике проекта, потому что там будет user: вместо group:.
Роли и привязки
Выдали доступ на весь проект, а нужен был один бакет — и сервис, у которого утёк ключ, читает всё. Чтобы права можно было резать точно, в Cloud IAM их выдают через пару «роль + привязка».
Роль (role) — набор разрешений. По ширине прав они делятся на три класса:
- базовые (basic) —
Owner,Editor,Viewerна весь проект (широкие, для практики почти всегда слишком грубые). Раньше их называли примитивными; в документации Google это слово больше не используется, искать нужно «basic roles»; - предопределённые (predefined) — узкие сервисные роли вида
roles/storage.objectAdmin(объекты в хранилище),roles/cloudsql.client(подключение к базе),roles/pubsub.publisher(публикация в тему). Это то, что нужно на практике; - пользовательские (custom) — свой набор разрешений, когда предопределённых не хватает.
Привязка (binding) — назначение «кому — какую роль — на каком ресурсе». Роль выдают на организацию, папку, проект или отдельный ресурс, и права наследуются вниз: роль на проект действует на все ресурсы внутри него. Обычно доступ выдают на уровне проекта.
Важная деталь, на которой спотыкаются пришедшие из AWS: привязки умеют только разрешать. Политика ресурса — это сумма всех привязок: если хоть одна даёт право, право есть. Строчки «а вот этому — запретить», как explicit Deny в AWS, внутри неё не существует. Запреты в GCP живут отдельно — это deny-политики, их пишут отдельным документом, и проверяются они раньше разрешающих. Пока вы их не завели, единственный способ отобрать право — убрать роль.
Так выглядит привязка: сервисному аккаунту приложения заказов — роль на объекты хранилища во всём проекте:
gcloud projects add-iam-policy-binding my-project \
--member="serviceAccount:orders-app@my-project.iam.gserviceaccount.com" \
--role="roles/storage.objectAdmin"
После запуска команда печатает обновлённую политику проекта целиком — вашу строку в ней видно сразу. Проверить, что легло, можно через gcloud projects get-iam-policy my-project, а снимается привязка той же командой с remove-iam-policy-binding.
Доступ без ключей: metadata и Workload Identity
Главное правило: ваш код не должен носить с собой ключи. Как приложение получает доступ, зависит от того, где оно работает:
- На виртуальной машине Compute Engine к ней привязывают сервисный аккаунт, и приложение получает временный токен прямо из сервера метаданных — без секретов в коде. Библиотеки Google находят его автоматически. Но одной роли тут мало: у машины есть ещё области доступа (access scopes), выбранные при её создании. Это второй фильтр поверх ролей, и классический тупик выглядит так: роль выдана, а вызов всё равно падает с отказом, потому что у машины области по умолчанию — например, хранилище только на чтение. Совет Google простой: ставьте машине полную область
cloud-platform, а права режьте ролями IAM, чтобы они были в одном месте, а не в двух. - В GKE используют Workload Identity — механизм, который связывает Kubernetes ServiceAccount с сервисным аккаунтом GCP, и под получает временный токен по той же модели.
- Извне облака (например, из CI не в GCP) раньше использовали JSON-ключ сервисного аккаунта — но это долгоживущий секрет и главный источник утечек. Современный способ — Workload Identity Federation: внешняя система (GitHub Actions, другой облачный провайдер) обменивает своё удостоверение на временный токен GCP без вечного ключа. Если ключ всё же нужен, его держат в защищённом хранилище, а не в git, и ротируют.
Правило: внутри облака — привязанный сервисный аккаунт и метаданные; federation вместо JSON-ключа; сам ключ — только там, где иначе никак.
Least privilege — минимум прав
Главный принцип всей безопасности: давать ровно столько прав, сколько нужно, и ни ролью больше.
Самый частый дефект новичка — выдать сервисному аккаунту Editor на весь проект «чтобы просто заработало». Так делают, чтобы не возиться, — и именно это потом превращается в инцидент: одна утёкшая учётка открывает весь проект.
Отдельная ловушка — сервисный аккаунт по умолчанию у Compute Engine. Исторически Google сам выдавал ему Editor на весь проект: машина, поднятая в два клика, работает с правами, которые вы бы ей руками никогда не дали. В организациях, созданных после 3 мая 2024 года, эта автоматическая выдача по умолчанию отключена (за неё отвечает ограничение iam.automaticIamGrantsForDefaultServiceAccounts), а вот в проектах постарше она осталась — стоит зайти и посмотреть, с какой ролью живёт аккаунт по умолчанию.
На практике least privilege — итеративный процесс: начните узко (только нужные предопределённые роли), запустите, посмотрите по отказам, чего не хватает, добавьте недостающую роль. Инструмент рекомендаций (IAM Recommender) подсказывает, какие выданные права реально не используются, — их стоит убирать.
Только не торопитесь с выводами после правки прав: изменения IAM применяются не сразу. Обычно новая роль начинает действовать через пару минут, иногда — через семь и дольше. Отказ сразу после выдачи роли почти всегда означает «ещё не доехало», а не «настроено неправильно», — подождите и повторите, а не выдавайте Editor от отчаяния.
Как читать отказ
Права выдавать научились — осталось разобраться, что делать, когда их не хватает. В GCP отказ выглядит так:
PERMISSION_DENIED: Permission 'storage.objects.get' denied on resource
'projects/_/buckets/orders-reports/objects/2026-09/report.csv' (or it may not exist)
Три части здесь полезны: какое разрешение не хватило (storage.objects.get), на каком ресурсе и оговорка «или он может не существовать» — GCP намеренно не различает «нет прав» и «нет ресурса», чтобы не выдавать существование объектов.
Дальше два инструмента.
Средство разбора политик (Policy Troubleshooter). Вы указываете, кто, какое разрешение и на каком ресурсе — и оно отвечает, есть ли доступ, и главное, почему: какая привязка его даёт или чего не хватает, с учётом наследования от организации и папок.
gcloud policy-intelligence troubleshoot-policy iam \
--principal-email=orders-app@acme-prod.iam.gserviceaccount.com \
--permission=storage.objects.get \
--resource=//storage.googleapis.com/projects/_/buckets/orders-reports
Это первое, куда идут: оно экономит перебор ролей вручную и учитывает то, что человек обычно забывает — наследование и запреты.
Журналы аудита (Cloud Audit Logs). Все административные операции пишутся всегда; отказы видны там же, с указанием личности, разрешения и ресурса. Для операций с данными (чтение файла, запрос к базе) журналирование включается отдельно и стоит денег — поэтому по умолчанию отказ на чтении объекта в журнале не появится, и это стоит знать заранее.
И практический порядок разбора: прочитать текст отказа целиком → найти в нём разрешение → прогнать средство разбора политик → проверить, не действует ли запрет или ограничение организации (о них раздел ниже) → и только потом искать ошибку в коде.
Ключи можно запретить целиком
В списке типичных ошибок стоит долгоживущий ключ служебной учётной записи, и у этой ошибки есть механизм, который делает её невозможной: ограничение организации iam.disableServiceAccountKeyCreation.
Включённое, оно означает, что создать ключ нельзя — ни в консоли, ни командой, никому, включая владельца организации. А раз ключей нет, то нет и утечек ключей.
gcloud resource-manager org-policies enable-enforce \
iam.disableServiceAccountKeyCreation --organization=123456789012
Как после этого работают те случаи, где раньше брали ключ:
- Код в GCP — служебная учётная запись присоединена к ресурсу, токен приходит из метаданных. Ключ не нужен изначально.
- Код вне GCP (другое облако, свой сервер, конвейер) — федерация удостоверений: внешняя личность получает временный токен GCP по доверию. Ключ не нужен.
- Локальная разработка — работа от имени учётной записи (см. раздел выше). Ключ не нужен.
- Совсем упрямый случай (старый инструмент, который умеет только ключ) — точечное исключение для одного проекта, с причиной и датой пересмотра.
Рядом полезно включить и срок жизни ключей (iam.serviceAccountKeyExpiryHours), если полный запрет пока невозможен: ключ перестаёт работать через заданное время, и «вечный ключ в репозитории» становится невозможным сам по себе.
Числа и границы
Несколько величин, которые полезно держать в голове.
Токен из метаданных живёт около часа (3600 секунд) и обновляется библиотекой автоматически. Практическое следствие: после отзыва прав у учётной записи работающее приложение может продолжать работать до истечения текущего токена — то есть «отозвали доступ» действует не мгновенно, а в пределах часа.
Число привязок в политике ограничено (порядка полутора тысяч на ресурс) — и это ещё один довод за группы: поимённые привязки заканчиваются быстрее, чем кажется, в большой организации.
Служебных учётных записей ограниченное число на проект (порядка сотни) — редко становится проблемой, но встречается в проектах, где заводят учётную запись на каждую задачу.
Предопределённые роли против своих. Предопределённая роль содержит набор разрешений, который меняет Google — обычно расширяет при появлении новых возможностей. Это удобно (не надо следить) и означает, что права могут незаметно вырасти. Своя роль содержит ровно то, что вы перечислили, и не меняется сама — зато следить за новыми разрешениями придётся вам. Отсюда практика: предопределённые роли для обычной работы, свои — для чувствительных мест, где точный список важнее удобства.
Где это применяется
Cloud IAM — это слой «кто что может делать» поверх сетевого слоя «кто до кого вообще может достучаться». Вместе они дают полноценную защиту: минимальная сеть плюс минимальные права.
Где вы столкнётесь с IAM сразу:
- Любой ваш сервис (виртуальные машины, функции, контейнеры) получает доступ через привязанный сервисный аккаунт.
- Конвейеры доставки кода работают через Workload Identity Federation, а не через зашитые JSON-ключи.
- Секреты и шифрование — соседняя тема: где хранить пароли, в безопасности и наблюдаемости.
Типичные ошибки новичков:
- Класть JSON-ключ сервисного аккаунта в код или git вместо привязки аккаунта к машине.
- Выдавать
Editor/Ownerшироко «чтобы заработало», а потом забыть сузить до предопределённых ролей. - Плодить JSON-ключи там, где работает Workload Identity Federation.
Глубже: где всё-таки запрет: IAM Deny и ограничения организациирасширенное
«Привязки умеют только разрешать» ставит вопрос, который задают все пришедшие из AWS: а как запретить? Например, запретить сотрудникам с широкой ролью удалять базы или запретить создавать ключи сервисных аккаунтов в принципе. Механизмов два, и оба живут отдельно от привязок.
Политики запрета IAM (IAM Deny policies). Отдельный тип политики, который проверяется раньше разрешений: если запрет совпал по субъекту и разрешению, доступа нет, какие бы роли ни были выданы. Пишут их на уровне организации или папки, для узкого набора разрешений (cloudsql.instances.delete для всех, кроме группы администраторов) и с исключениями по принципалам. Это не замена узким ролям, а страховка от широких: у команды остаётся Editor на своём проекте, но удалить прод-базу она не может.
Ограничения организации (organization policy). Правила о том, какие ресурсы вообще можно создавать и в каком виде, независимо от прав: запрет создавать ключи сервисных аккаунтов (iam.disableServiceAccountKeyCreation), запрет публичного доступа к бакетам (storage.publicAccessPrevention), запрет внешних адресов у машин (compute.vmExternalIpAccess), список разрешённых регионов (gcp.resourceLocations), обязательные защищённые машины. Их ставят на организацию и наследуют вниз, и это самый дешёвый способ закрыть половину типичных ошибок раздела ещё до того, как кто-то их совершит. Свежая организация без этих пяти ограничений это выбор, а не умолчание.
Периметр вокруг данных. Права отвечают «кто может», а не «откуда»: утёкшие учётные данные с правом на бакет читают его из любой точки интернета. VPC Service Controls рисуют периметр вокруг проектов и сервисов: вызов API хранилища или BigQuery проходит только изнутри периметра (из вашей сети или через приватный доступ), а снаружи отвергается даже с валидным токеном. Это защита от утечки данных, а не от ошибок прав, и её включают для проектов с персональными данными.
Как это укладывается с остальным: привязки дают минимум прав, запреты страхуют от широких ролей, ограничения организации запрещают опасные конфигурации, периметр закрывает доступ извне. Проверяют результат одним инструментом: анализатор политик показывает, кто и через что имеет разрешение на ресурс, с учётом наследования и запретов, и это первое, что открывают при вопросе «почему у него есть доступ».
Коротко
- Людям пользователи, программам сервисные аккаунты; JSON-ключ в коде это главный источник утечек.
- Права выдают парой роль плюс привязка на организацию, папку, проект или ресурс, и они наследуются вниз; узкие предопределённые роли вместо
Editor. - Внутри облака код берёт токен из метаданных или через Workload Identity, снаружи через федерацию удостоверений; изменения прав применяются минуты.
- Привязки только разрешают: запрет делают политики IAM Deny, опасные конфигурации закрывают ограничения организации, доступ извне отсекает периметр VPC Service Controls.
Что почитать дальше
- Безопасность и наблюдаемость в GCP — секреты, шифрование и журналы аудита.
- Сеть в GCP — приватный доступ к сервисам, внутри которого работает периметр.
- Права и учётные записи в облаке — та же модель без привязки к провайдеру.