Правильная роль - не та, что позволяет запрос, а та, что не позволяет лишний запрос. Если ты настроил сервисный аккаунт, дернул модель, получил ответ 200 и на этом закрыл задачу авторизации, ты проверил ровно одно: аккаунт может делать то, что должен. Ты не проверил главное - что он не может делать то, чего не должен.
Это два разных утверждения, и в security они не эквивалентны. Успешный вызов подтверждает наличие нужного разрешения. Он ничего не говорит про отсутствие лишних. Аккаунт с ролью roles/aiplatform.admin тоже пройдет твой предикт-запрос - и заодно сможет удалять эндпоинты, читать и переписывать IAM-политику на ресурсах Vertex и запускать batch-задания. С точки зрения «запрос прошел» обе конфигурации выглядят одинаково зелеными.
Разберем протокол, который эту разницу делает наблюдаемой: пара из одного разрешенного и одного намеренно запрещенного учебного вызова, каждый с заранее записанным ожидаемым статусом. Документированной процедурой Google это не является - это инженерный метод, и дальше по тексту я отмечаю явно, где кончается документация и начинается моя реконструкция.
Подключите модели для проверки контента с оплатой в рублях на provod.ai
Что на самом деле доказывает успешный вызов?
Дефолт, с которым спорит эта статья: «успешная авторизация означает корректно настроенные IAM-права». На практике успешная авторизация означает, что у вызывающего есть привязка роли, содержащая нужное разрешение. Верхнюю границу его полномочий она не измеряет.
Официальная security-рекомендация Google Cloud (docs.cloud.google.com, доступ 18 июля 2026) прямо советует выдавать наиболее ограниченные предопределенные или кастомные роли, которых хватает под задачу, применять их на минимально возможном уровне ресурса и заводить отдельные сервисные аккаунты на компонент с разными наборами разрешений. Это нормативная опора: один зеленый вызов не является доказательством least privilege, потому что он проверяет достаточность, а не минимальность.
Твоя ставка как разработчика тут вполне материальная. Лишние права труднее заметить после запуска - они не мешают работе, ничего не ломают в тестах и всплывают только при аудите или инциденте. Неправильная схема авторизации либо задерживает релиз, когда её ловят на ревью, либо создает тихий избыточный доступ, который живет месяцами.
Оговорка на случай, если часть запросов у тебя уходит во внешний совместимый контур - скажем, в provod.ai (российский аналог OpenRouter). Там аутентификация устроена по ключу и к IAM твоего проекта Google Cloud отношения не имеет. Минимальность прав сервисного аккаунта этот маршрут за тебя не проверит и проверять не должен; к разнице между двумя моделями авторизации вернемся отдельно.
Какие роли Vertex дают минимум, а какие лишнее?
Vertex AI публикует предопределенные IAM-роли в пространстве разрешений aiplatform.*. По документации ролей (docs.cloud.google.com, доступ 18 июля 2026) roles/aiplatform.admin (Vertex AI / Agent Platform Administrator) выдает wildcard aiplatform.* - полный доступ ко всем ресурсам Vertex, включая агентов, batch-задания, эндпоинты и управление IAM-политикой на этих ресурсах. Для сервисного аккаунта, которому нужно только вызывать развернутую модель, это заведомо избыточно.
Более узкая роль для той же задачи - roles/aiplatform.user (Vertex AI User). Она содержит разрешение aiplatform.endpoints.predict, а именно оно требуется для вызова inference/prediction. Это тот минимум, вокруг которого строится тест: целевое действие - предикт - должно проходить под aiplatform.user, а лишнее действие уровня админа - нет.
Отдельно про базовые роли. Официальная страница access control для Vertex AI (docs.cloud.google.com, доступ 18 июля 2026) отмечает, что предопределенные роли дают разрешения на уровне проекта, тогда как базовые роли Owner/Editor/Viewer шире и общие для всех сервисов Google Cloud. Для теста на минимальность базовые роли не годятся по определению: они не про Vertex, они про всё сразу.
Здесь же стоит снять путаницу в самой постановке задачи, иначе проверять будет нечего. Документацию по вызову моделей ты найдешь под именами vertex ai api и google vertex ai api, и это именно то, что нужно. А вот vertex ai api key описывает модель авторизации, которой для серверных вызовов Vertex, как правило, нет: доступ там строится на сервисном аккаунте и IAM-ролях. Если во внутреннем гайде или в тикете стоит «нужен api key для Vertex», задачу надо переформулировать до того, как она попадет в код: нужен сервисный аккаунт с ролью, содержащей aiplatform.endpoints.predict. У строки-ключа ролей нет, и сужать в ней нечего - вместе с формулировкой из задачи исчезает сам предмет проверки.

Как построить пару «разрешено - запрещено»?
Метод простой и намеренно узкий. Берешь одно действие, которое роль обязана разрешать, и одно, которое обязана запрещать, выполняешь оба изолированно и записываешь фактический статус рядом с ожидаемым. Разрешенный вызов должен вернуть успех. Запрещенный - вернуть отказ. Если запрещенный проходит, гипотеза о минимальности роли опровергнута; это и есть фальсифицируемое условие всего протокола.
Сигнал отказа документирован точно. По странице про permission-ошибки IAM (docs.cloud.google.com, доступ 18 июля 2026), при отсутствии у вызывающего роли с нужным разрешением (или при блокировке deny-политикой либо access boundary) возвращается PERMISSION_DENIED; REST API отдает HTTP 403 со структурированным payload google.rpc.ErrorInfo, где названо конкретное недостающее разрешение и уникальный идентификатор ошибки. Логировать надо именно это: имя разрешения и код. Запись «что-то не сработало» в журнале бесполезна.
До живого мутирующего вызова полезно свериться неразрушающе. Метод testIamPermissions() (docs.cloud.google.com, доступ 18 июля 2026) принимает идентификатор ресурса и список строк-разрешений и возвращает только то подмножество, которым вызывающий реально владеет. То есть можно программно спросить: держит ли этот аккаунт aiplatform.endpoints.predict - и держит ли он что-то лишнее, чего в списке быть не должно.
Ниже - каркас проверки. Это шаблон метода, а не готовый прогон: реального журнала выполненного теста в источниках нет, любой лог здесь - предлагаемый образец.
from google.api\_core.exceptions import PermissionDenied # test\_iam\_permissions / call\_predict / delete\_endpoint - твои обёртки над клиентом Vertex
# 1. Неразрушающая проверка: что аккаунт РЕАЛЬНО держит resource = "projects/PROJECT/locations/REGION/endpoints/ENDPOINT\_ID" wanted = ["aiplatform.endpoints.predict"] # целевое, должно быть excess = ["aiplatform.endpoints.delete"] # лишнее, должно отсутствовать
held = test\_iam\_permissions(resource, wanted + excess) # subset, реально held
assert "aiplatform.endpoints.predict" in held, "целевое действие не покрыто ролью" assert "aiplatform.endpoints.delete" not in held, "лишнее разрешение присутствует"
# 2. Разрешённый живой вызов: ожидаем успех predict\_response = call\_predict(resource) # ожидаемый статус: 200/OK
# 3. Запрещённый живой вызов, изолированно: ожидаем отказ try: delete\_endpoint(resource) # ожидаемый статус: 403 raise AssertionError("запрещённое действие прошло - роль НЕ минимальна") except PermissionDenied as e: log\_denial(permission="aiplatform.endpoints.delete", status=403, error\_info=str(e)) # фиксируем имя и код
Ключевое ограничение метода записано прямо в шаге 3: запрещенный вызов выполняется изолированно и над безопасным ресурсом, потому что это реальное мутирующее действие. Если бы у аккаунта нашлось лишнее право на delete, вызов бы его выполнил. Поэтому боевую проверку избыточных прав разумнее держать на testIamPermissions(), а живой отрицательный вызов - на заведомо расходуемом учебном эндпоинте.

В этом журнале отказ засчитывается как успех
Журнал - это не отчет «всё зелено». Это таблица, где у каждого действия заранее прописан ожидаемый статус, а прогон лишь подтверждает или опровергает его. Отказ в строке лишнего действия - не ошибка теста, а его успех. Это переворачивает привычную семантику логов, и именно поэтому статус отказа надо фиксировать явно: незаписанный PERMISSION_DENIED не считается результатом.
Матрица ниже - учебный образец под роль aiplatform.user. В ней намеренно нет «универсальной роли»: набор действий фиксирован, и вывод о минимальности справедлив только в его пределах.
| Учебное действие | Разрешение | Ожидаемый под aiplatform.user | Что означает отклонение |
|---|---|---|---|
| Вызвать предикт на эндпоинте | aiplatform.endpoints.predict | 200 / OK | Если 403 - целевое действие не соответствует роли |
| Удалить эндпоинт | aiplatform.endpoints.delete | 403 / PERMISSION_DENIED | Если 200 - роль шире цели, не минимальна |
| Изменить IAM-политику ресурса | из wildcard aiplatform.* (admin) | 403 / PERMISSION_DENIED | Если 200 - выдана admin-эквивалентная роль |
Проверка testIamPermissions на predict | - | predict в held | Пусто - целевое право отсутствует |
Проверка testIamPermissions на delete | - | delete не в held | Присутствует - лишнее право |
Три условия, при которых тест считается проваленным, стоит держать перед глазами: лишнее действие разрешено; целевое действие не соответствует роли (не проходит там, где обязано); статус отказа не зафиксирован. Первое опровергает минимальность, второе - достаточность, третье лишает тебя доказательства как такового.
Честно про границы уверенности. Зафиксированные разрешенные и запрещенные вызовы - установленный результат: они записаны в журнале. Что ожидаемые отказы подтверждают минимальность роли - вывод вероятный и только в пределах тестовой матрицы. Достаточна ли роль для будущих сценариев вне набора тестов - неизвестно; матрица этого не измеряет и на это не претендует.

Чем Vertex-авторизация отличается от ключа во внешнем API?
Тут полезно сравнение, потому что модель авторизации Vertex часто путают с моделью «один ключ - и поехали», к которой привыкли по OpenAI- и Anthropic-совместимым сервисам. В Vertex доступ - это сервисный аккаунт плюс IAM-роль на уровне ресурса или проекта, с раздельными наборами разрешений и возможностью кастомного сервисного аккаунта (docs.cloud.google.com подтверждает отдельную статью «Use a custom service account», доступ 18 июля 2026). Проверяешь ты там роль. Строка сама по себе не ограничивает ничего.
В OpenAI- и Anthropic-совместимом контуре модель другая: ты меняешь ключ и base_url, и SDK начинает ходить в другой апстрим. Так устроен и provod.ai - один совместимый API к доступным на платформе моделям, куда клиент, агент или IDE с поддержкой такого протокола подключается заменой этих двух значений. Внешне это выглядит как та же задача «настроить доступ», и именно поэтому две модели путают.
# Внешний совместимый контур: авторизация = ключ + base\_url from openai import OpenAI client = OpenAI(api\_key="PROVOD\_KEY", base\_url="https://api.provod.ai/v1") # в Vertex так нельзя: там сервисный аккаунт + IAM-роль, а не строка-ключ
Разница принципиальная для темы статьи. Смена ключа не дает тебе рычага least privilege на уровне действий: границу твоих возможностей провел провайдер, когда выдал ключ, и подвинуть ее на уровень отдельных вызовов ты не можешь. В Vertex рычаг есть - и отрицательный тест как раз способ им воспользоваться. Контуры разные, задачи разные, один не подменяет другой.
Policy Simulator усиливает вывод, но только задним числом
Прежде чем расширять роль, изменение можно прогнать вхолостую. Policy Simulator (roles/policysimulator.admin, разрешения policysimulator.replays.create/get/list/run) - официальный инструмент Google Cloud (docs.cloud.google.com, доступ 18 июля 2026), который переигрывает прошлые попытки доступа против предлагаемого изменения политики и показывает, какие разрешения станут заново разрешенными или заново запрещенными до применения. Для проверки «не выйдет ли новая роль за рамки задуманного» это дополняющий, неживой способ.
Но у симулятора есть встроенная граница, о которой важно сказать честно. По обзорной документации (docs.cloud.google.com, доступ 18 июля 2026), результаты симуляции строятся на логах доступа за последние 90 дней и сообщают, какие попытки сменили бы исход при предлагаемой политике. То есть Policy Simulator валидируется против наблюдавшихся исторических вызовов, а не против исчерпывающего перечня всех возможных будущих действий. Он подтверждает твой вывод там, где действия уже случались, и молчит там, где их еще не было.
Из этого следует связка методов, а не выбор одного: testIamPermissions() отвечает на вопрос «что аккаунт держит прямо сейчас», живой отрицательный вызов дает документированный PERMISSION_DENIED с именем разрешения, а Policy Simulator оценивает эффект изменения на фоне реального трафика. Ни один из трех не превращается в полный аудит IAM в одиночку.

Чего этот метод не решает
Матрица из пары вызовов - узкий инструмент. Его пределы стоит назвать прямо, пока журнал не начали предъявлять как отчет об аудите.
Он не заменяет полный аудит IAM. Он проверяет конкретные действия из твоего списка, а не все разрешения роли. Каталог ролей и разрешений Vertex версионируется и меняется; конкретный список разрешений верен на дату теста (18 июля 2026) и постоянным не является. Значит, тест надо перепрогонять при изменении роли или обновлении каталога, а не считать однажды полученный зеленый журнал вечным.
Он не покрывает будущие действия. Корректный отказ на заданное лишнее действие поддерживает вывод о least privilege только в границах тестовой матрицы. Появится новый сценарий - появится новая строка, которую никто пока не проверял. Достаточность роли за пределами набора тестов остается неизвестной, и честнее держать это открытым вопросом, чем закрывать его удобным допущением.
И он ничего не говорит про внешний API-контур. provod.ai не заменяет IAM-проверку Vertex: это отдельный совместимый API с собственной аутентификацией, он не выдает роли в твоем проекте Google Cloud и не проверяет их за тебя. Обратное тоже верно - чистый журнал Vertex не аттестует ничего за пределами Vertex.
Итог и следующий шаг
Считай роль минимальной только после корректного отрицательного теста. Одного зеленого предикта недостаточно: он подтверждает, что аккаунт может делать нужное, и молчит про то, чего он делать не должен. Практическое решение - завести журнал «разрешенное действие - запрет - ожидаемый статус», прогнать пару вызовов изолированно, зафиксировать PERMISSION_DENIED с именем разрешения и перепрогонять матрицу при каждом изменении роли.
FAQ
Разве успешный вызов Vertex AI API не достаточен как проверка авторизации?
Он достаточен как проверка достаточности: аккаунт может сделать то, что должен. Минимальность он не измеряет - под aiplatform.admin тот же вызов пройдет с полным wildcard-доступом. Нужен отрицательный тест.
Почему запрос vertex ai api key ведет не туда?
Для серверных вызовов Vertex авторизация обычно строится на сервисном аккаунте и IAM-роли с aiplatform.endpoints.predict, а не на строке-ключе. Формулировку про «ключ» стоит переписать в терминах сервисного аккаунта и роли.
Зачем живой запрещенный вызов, если есть testIamPermissions()?
testIamPermissions() показывает, что аккаунт держит, неразрушающе. Живой вызов дает документированный PERMISSION_DENIED с HTTP 403 и именем недостающего разрешения - это тот сигнал, который логируется как доказательство. Живой отрицательный вызов держи изолированно и на расходуемом ресурсе.
Может ли Policy Simulator заменить пару вызовов?
Нет. Он оценивает эффект изменения политики против логов за 90 дней, то есть против уже наблюдавшихся вызовов. Действия, которых в истории не было, он не покрывает.
Годятся ли базовые роли Owner/Editor для минимального теста?
Нет. По документации Vertex они шире и общие для всех сервисов Google Cloud, а не привязаны к aiplatform.*. Для проверки минимальности бери предопределенные или кастомные роли.

provod.ai — сократите интеграционный зоопарк вокруг AI
Один совместимый API заменяет отдельную обвязку каждого вендора: разработчики быстрее добавляют AI-функции, а продуктовая команда свободнее выбирает модель под качество, скорость и задачу.
В одном каталоге — актуальные модели для текста и медиа: GPT от OpenAI, Claude от Anthropic, Gemini от Google, Grok от xAI, DeepSeek, Qwen, GLM, Kimi и MiniMax; для изображений — Nano Banana 2 Pro и GPT Image; для видео — последние версии Seedance, Kling, Veo и Google Omni. Также доступны модели для reasoning, поиска, документов, эмбеддингов, музыки и аудио.
За удобство роутинга нет отдельной ценовой надбавки: стоимость остаётся 1:1 с официальной ценой поставщика, а расчёты собираются на одном рублёвом балансе.
Упростите AI-архитектуру продукта: форма регистрации · цены на модели · защита данных по 152-ФЗ · главная provod.ai
Источники
- Google Cloud, IAM roles/permissions for Vertex AI (
aiplatform.admin,aiplatform.user,aiplatform.endpoints.predict), docs.cloud.google.com, доступ 2026-07-18. - Google Cloud, Access control for Vertex AI (предопределенные и базовые роли), docs.cloud.google.com, доступ 2026-07-18.
- Google Cloud, Permission errors (
PERMISSION_DENIED, HTTP 403,google.rpc.ErrorInfo), docs.cloud.google.com, доступ 2026-07-18. - Google Cloud, Testing permissions (
testIamPermissions()), docs.cloud.google.com, доступ 2026-07-18. - Google Cloud, Using IAM securely (least-privilege guidance), docs.cloud.google.com, доступ 2026-07-18.
- Google Cloud, Policy Simulator и обзор (окно логов 90 дней), docs.cloud.google.com, доступ 2026-07-18.
- Google Cloud, Use a custom service account for Vertex AI, docs.cloud.google.com, доступ 2026-07-18.
