Сервисные аккаунты Cloud
Сервисный аккаунт — это машинная учётная запись для CI-конвейеров, интеграций
и автоматизации. Он принадлежит вашему биллинг-аккаунту, создаётся в кабинете
Cloud в разделе Интеграции → Сервисные аккаунты и расходует одну единицу
отдельного лимита сервисных аккаунтов вашего тарифа.
Используйте сервисный аккаунт, когда в Пространстве работает программа, а не
человек. Не передавайте CI-задаче обычный API-токен: API-токен несёт права
того, кто его создал, вплоть до администрирования Пространства. Сервисный
аккаунт — нет.
Что сервисный аккаунт может и чего не может
При создании сервисный аккаунт привязывается к одному Пространству с набором
прав. Выдать можно только эти права:
| Право | Что разрешает |
|---|---|
| Читать Пространство | Видеть само Пространство |
| Читать участников | Видеть, кто входит в Пространство |
| Читать биллинг | Видеть состояние биллинга Пространства |
| Запускать работу | Запускать тесты, фаззинг и другую работу в Пространстве |
| Читать общие проекты | Смотреть список общих проектов и читать их |
| Изменять общие проекты | Создавать, изменять и удалять общие проекты |
Запускать работу и оба права на общие проекты действуют только в
Пространствах команды (Team). На других тарифах кабинет предлагает лишь три
права на чтение, а API отказывает в остальных с кодом
service_account_team_required.
Администрирования в этом списке намеренно нет. Сервисному аккаунту нельзя
выдать право менять роли, приглашать и удалять участников или менять биллинг:
машинные учётные данные с такими правами — это админский токен под другим
названием.
Привязка неизменяема
Привязка к Пространству и её набор прав записываются один раз. Изменить их
после этого нельзя — ни вам, ни оператору, ни самому сервисному аккаунту. В
этом и состоит защитное свойство функции: сервисный аккаунт не может расширить
свои права сам, и никто не может тихо сделать из него администратора.
Если набор прав нужно изменить, отзовите сервисный аккаунт и создайте новый.
Отозванный аккаунт и его привязка остаются в истории аудита.
Один сервисный аккаунт можно привязать к нескольким Пространствам, но каждая
привязка создаётся со своим неизменяемым набором прав, и сервисный аккаунт всё
равно расходует ровно одну единицу лимита, сколько бы Пространств у него ни было.
Для создания, привязки, выдачи или замены учётных данных и отзыва сервисного
аккаунта нужна текущая роль владельца или администратора Пространства. Для
привязки ко второму Пространству такая роль нужна в обоих Пространствах. В
Пространстве команды также должны быть активны ваше членство в команде и
закреплённое за вами место. Если команда или ваш доступ приостановлены,
управление будет отклонено до восстановления доступа владельцем команды.
Учётные данные
При создании сервисного аккаунта можно сразу выдать первые учётные данные,
выбрав эту опцию.
Новые или заменённые учётные данные показываются ровно один раз; восстановить
их нельзя. Сразу сохраните их в хранилище секретов вашего CI. Пока выдача или
замена не завершена, кабинет не позволит уйти со страницы или переключить
Пространство. Когда данные уже показаны, случайный уход потребует подтверждения.
Если аккаунт изменился, а одноразовые данные не пришли, не повторяйте
Создать: откройте существующий аккаунт и выдайте или замените данные.
Учётные данные:
- имеют собственный префикс
msa_и не являются API-токеном Cloud; - принимаются только на эндпоинтах сервисного аккаунта — предъявление их
где-либо ещё отклоняется с явной причиной; - не могут быть прочитаны обратно из сервиса, поэтому потерянные учётные данные
заменяют, а не восстанавливают; - могут иметь срок действия (0 дней — без срока);
- показывают время последнего использования, чтобы можно было найти учётные
данные, которыми больше никто не пользуется.
У сервисного аккаунта не более одних действующих учётных данных. Чтобы
заменить их, используйте Заменить учётные данные: предыдущие отзываются, а
новые выдаются в одной операции. Поэтому не бывает ни момента с двумя рабочими
секретами, ни момента без секрета вообще.
Отзыв
Отзыв сервисного аккаунта необратим. В одной операции он:
- отзывает действующие учётные данные — они перестают работать сразу;
- помечает сервисный аккаунт отозванным;
- освобождает единицу лимита сервисных аккаунтов.
Отменить отзыв нельзя; создайте новый сервисный аккаунт. Привязки и история
учётных данных остаются в журнале аудита.
Как узнать у учётных данных их права
Владелец учётных данных может прочитать свою личность, привязки, действующие
права и время последнего использования:
curl -sS -H "Authorization: Bearer msa_…" \
https://cloud.example.com/api/v1/cloud/service-account/self
А также проверить одно право в одном привязанном Пространстве — так интеграция
сообщает о проблеме с правами до того, как упадёт операция:
curl -sS -H "Authorization: Bearer msa_…" \
"https://cloud.example.com/api/v1/cloud/service-account/spaces/<SPACE_ID>/authorize?capability=shared.project.write"
Если Пространство не привязано, ответ — not_bound (404), а не false: так
ошибка в настройке Пространства отличается от отсутствующего права.
Управление из CLI
mockarty-cli cloud-service-accounts list <SPACE_ID>
mockarty-cli cloud-service-accounts get <SPACE_ID> <ACCOUNT_ID>
mockarty-cli cloud-service-accounts create <SPACE_ID> \
--name ci-runner \
--capability space.read --capability shared.project.write \
--issue-credential --credential-ttl-seconds 7776000 \
--idempotency-key "$(uuidgen)"
mockarty-cli cloud-service-accounts bind <SPACE_ID> <ACCOUNT_ID> \
--target-space <OTHER_SPACE_ID> --capability execute \
--idempotency-key "$(uuidgen)"
mockarty-cli cloud-service-accounts rotate-credential <SPACE_ID> <ACCOUNT_ID> \
--idempotency-key "$(uuidgen)"
mockarty-cli cloud-service-accounts revoke <SPACE_ID> <ACCOUNT_ID> \
--idempotency-key "$(uuidgen)"
Каждому изменяющему вызову управления нужен --idempotency-key: именно он
делает безопасным повторный запрос, когда ответ теряется в сети. Для создания,
привязки, выдачи учётных данных и отзыва также нужно интерактивное подтверждение
service_account step-up. Обычный API-токен mk_ не заменяет это
подтверждение.
Работа с учётными данными msa_
Передайте учётные данные CLI как токен. CLI распознаёт префикс msa_ и
отправляет его только как Authorization: Bearer:
mockarty-cli --token "$MOCKARTY_SERVICE_ACCOUNT_CREDENTIAL" cloud-service-account self
mockarty-cli --token "$MOCKARTY_SERVICE_ACCOUNT_CREDENTIAL" cloud-service-account authorize \
--space <SPACE_ID> --capability shared.project.write
Для активного сервисного аккаунта Team отдельный машинный маршрут общих
проектов включается флагом --service-account. Изменяющему машинному вызову
нужен ключ идемпотентности; --request-id относится к пользовательскому
маршруту и в этом режиме не используется:
mockarty-cli --token "$MOCKARTY_SERVICE_ACCOUNT_CREDENTIAL" cloud-shared-projects list \
--service-account --space <SPACE_ID>
mockarty-cli --token "$MOCKARTY_SERVICE_ACCOUNT_CREDENTIAL" cloud-shared-projects create \
--service-account --space <SPACE_ID> --name smoke-suite \
--body-file project.json --idempotency-key "$(uuidgen)"
Активные учётные данные Team с правами запуска могут также запускать, читать и
отменять Shared runs. Лимиты и стоимость работы относятся к Пространству,
которое принимает запуск. Повторно используйте один ключ идемпотентности только
для точного повтора того же запуска или отмены:
mockarty-cli --token "$MOCKARTY_SERVICE_ACCOUNT_CREDENTIAL" cloud-service-account runs dispatch \
--space <SPACE_ID> --project <PROJECT_ID> --capability execute --class batch \
--deadline 2026-09-21T20:00:00Z --payload-file run.json \
--idempotency-key "$(uuidgen)"
mockarty-cli --token "$MOCKARTY_SERVICE_ACCOUNT_CREDENTIAL" cloud-service-account runs get <RUN_ID> \
--space <SPACE_ID>
mockarty-cli --token "$MOCKARTY_SERVICE_ACCOUNT_CREDENTIAL" cloud-service-account runs cancel <RUN_ID> \
--space <SPACE_ID> --revision <REVISION> --idempotency-key "$(uuidgen)"
Не добавляйте operation_id в тело запуска. Cloud выводит его из
Idempotency-Key; переданное значение принимается только при точном совпадении
с этим результатом.
SDK
Во всех поддерживаемых SDK управление человеком отделено от машинной нагрузки:
| SDK | Управление человеком | Учётные данные msa_ и нагрузка |
|---|---|---|
| Go | client.CloudServiceAccounts() |
client.CloudServiceAccount() |
| Python | client.cloud_service_accounts |
client.cloud_service_account |
| Java | client.cloudServiceAccounts() |
client.cloudServiceAccount() |
Каждому разрешённому сервисному аккаунту доступны self и authorize.
Активному сервисному аккаунту Team также доступны CRUD общих проектов и
dispatch/get/cancel для запусков. Для запуска и отмены вызывающая сторона
обязана передать стабильный ключ идемпотентности. В запросе запуска SDK
намеренно нет поля operation_id.
MCP для автоматизации Team
Активный сервисный аккаунт Team может подключить MCP-клиент к отдельному
Streamable HTTP endpoint:
https://cloud.example.com/api/v1/cloud/service-account/mcp
Authorization: Bearer msa_…
Этот endpoint принимает только активные учётные данные msa_, принадлежащие
активному биллинг-аккаунту Team. Личный сервисный аккаунт, API-токен mk_ и
сессия кабинета отклоняются. Этот транспорт отделён от общего MCP-сервера,
который работает на узле Mockarty.
Cloud MCP содержит следующие инструменты:
| Сценарий | Инструменты |
|---|---|
| Идентификация и проверка разрешения | cloud_service_account_self, cloud_service_account_authorize |
| Общие проекты | cloud_shared_projects_list, cloud_shared_project_get, cloud_shared_project_create, cloud_shared_project_update, cloud_shared_project_delete |
| Общие запуски | cloud_shared_run_dispatch, cloud_shared_run_get, cloud_shared_run_cancel |
Каждый инструмент, кроме cloud_service_account_self, явно принимает целевой
space_id. Затем Cloud проверяет неизменяемую привязку сервисного аккаунта и
его разрешения для этого Пространства. Квоты и стоимость принадлежат
принимающему Пространству Team, поэтому привязка одного сервисного аккаунта к
нескольким Пространствам не переносит их расход в его домашнее Пространство.
Для создания, изменения и удаления проекта, а также запуска и отмены нужны
idempotency_key. Повторно используйте ключ только для той же самой мутации.
Инструмент запуска не принимает operation_id: Cloud выводит его из ключа.
JSON проекта ограничен 1 МиБ, а необязательная нагрузка запуска — 16 КиБ.
Транспорт использует тот же runtime proxy, проверки разрешений и аудит, что и
REST-маршруты сервисного аккаунта. Он никогда не возвращает короткоживущий
runtime-токен, с которым Cloud обращается к Shared runtime.
Места
Сервисный аккаунт занимает отдельный лимит сервисных аккаунтов тарифа, а не
человеческое место. Добавление ещё одной привязки не расходует лимит повторно, а освобождение
человеческого места (наблюдатель, менеджер биллинга или ушедший участник) никак
не зависит от сервисных аккаунтов. Отзыв сервисного аккаунта освобождает его
лимит в той же операции.
Free включает 1 сервисный аккаунт, Pro — 5, Pro+ — 10. Пакет Team
включает не больше одного сервисного аккаунта на каждое купленное место пакета:
5, 10 или 20; эти машинные учётные записи не занимают человеческие места.
Enterprise работает на абсолютном потолке 64. Лимит принадлежит
биллинг-аккаунту: новые Пространства, привязки, токены и устройства его не
умножают. Когда лимит исчерпан, создание нового аккаунта отклоняется ответом
429 quota_exceeded (metric: service_accounts).