Agentic CI/CD: OIDC, runner и безопасный деплой

AI в pipeline — не кнопка «сделай красиво». Агент читает чужой pull request, запускает shell, меняет файлы и иногда просит доступ в облако. Значит, относиться к нему надо как к недоверенному исполнителю, который работает на недоверенном входе и очень убедительно объясняет свои ошибки.

Автор — Дмитрий Тыльный · опыт Senior DevOps · 7 сентября 2026 · 13 мин

Коротко. На pull request агент получает только чтение и создаёт проверяемый артефакт: отчёт, patch или draft PR. Доступ к облаку выдаётся короткоживущим OIDC-токеном только доверенной ветке и environment. Runner одноразовый, сеть и команды ограничены, production требует ручного approval, а diff, tool calls и результаты тестов сохраняются.

Агент в CI — не генератор YAML

Попросить чат написать workflow и проверить его руками — обычная разработка с подсказкой. Agentic CI/CD начинается, когда модель сама выбирает файлы, команды и следующий шаг: разбирает падение теста, предлагает исправление, обновляет dependency или готовит deploy plan.

Чем больше свободы, тем важнее жёсткая рамка вне промпта. Фраза «никогда не трогай production» внутри инструкции слабее, чем отсутствие сетевого маршрута и cloud role без права записи.

Что реально может пойти не так

  • PR poisoning. Текст issue, README или теста содержит инструкцию вытащить секреты.
  • лишние permissions. Workflow по умолчанию умеет писать в репозиторий или получать токен облака.
  • грязный runner. Следующий job читает файлы, процессы или credentials предыдущего.
  • бесконечная петля. Агент снова запускает тест, снова правит код и сжигает минуты.
  • тихий большой diff. Полезное изменение приезжает вместе с удалением проверки или ослаблением policy.
  • непроверенный deploy. Модель перепутала окружение, а pipeline послушно выполнил.

Минимальные permissions в workflow

name: agent-review
on:
  pull_request:

permissions:
  contents: read

jobs:
  review:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4
        with:
          persist-credentials: false
      - run: ./ci/run-agent-review.sh
      - uses: actions/upload-artifact@v4
        with:
          name: agent-report
          path: out/report.md

На недоверенном PR нет id-token: write, production secrets и права пушить. Если нужен комментарий, вынесите публикацию в отдельный доверенный job, который читает только подготовленный артефакт и экранирует содержимое.

OIDC вместо вечного ключа

Для доверенного deploy job GitHub может выдать OIDC-токен. Облачный провайдер проверяет issuer, audience и subject, после чего выдаёт короткую сессию. В GitHub остаётся право запросить токен, но не лежит многолетний access key.

permissions:
  contents: read
  id-token: write

jobs:
  deploy:
    environment: production
    concurrency: production
    runs-on: ubuntu-latest

Само id-token: write не делает схему безопасной. В trust policy провайдера зафиксируйте репозиторий, организацию, ветку или environment и ожидаемый aud. Условие «любой workflow из организации» — почти тот же мастер-ключ, только современно оформленный.

Runner должен умирать после job

Одноразовый runner проще очищать, чем обещать, что вечная машина идеально убрана. После задачи уничтожаются workspace, контейнер и временные credentials. Docker socket, домашний каталог администратора и общая cache директория агенту не нужны.

Сетевой egress ограничьте registry, API модели и необходимыми сервисами. Если агент может отправить данные на любой адрес, никакой redaction в логах не спасёт. Для self-hosted runner разделите пул недоверенных PR и пул deploy: у них разный риск и разные маршруты.

Что можно автоматизировать, а что подтверждать

Разрешите агенту читать, классифицировать, запускать тесты и готовить patch. Запись в защищённую ветку, миграция, удаление ресурса и production deploy проходят через человека или отдельную детерминированную policy.

  • не больше 8 изменённых файлов за один проход;
  • запрет изменения workflow, IAM и policy без отдельного класса задачи;
  • обязательные тесты и линтер после diff;
  • запрет force push и прямого merge;
  • лимит tool calls, времени и стоимости;
  • approval с отображением точного plan, а не текста «всё безопасно».

Артефакт важнее ответа модели

Сохраняйте исходный commit, версию модели и инструкции, список прочитанных и изменённых файлов, разрешённые команды, diff, результаты тестов, policy decisions и идентификатор OIDC-сессии. Полные prompts и секреты сохранять не надо.

Трасса должна позволять ответить: какой вход породил действие, какое правило его разрешило, что реально выполнилось и кто подтвердил production. Схема наблюдаемости разобрана в статье про OpenTelemetry для AI-агентов.

Безопасная последовательность

  1. Недоверенный PR запускает read-only анализ на одноразовом runner.
  2. Агент формирует patch и отчёт, но не пушит.
  3. Обычный CI проверяет patch детерминированными тестами.
  4. Человек принимает небольшой diff.
  5. После merge доверенный workflow строит подписанный артефакт.
  6. Deploy job проходит environment approval и получает короткий OIDC-доступ.
  7. Production применяет уже проверенный артефакт, а не новый ответ модели.

Для происхождения сборки добавьте provenance и подпись из гайда про SBOM/SLSA. Для первого обычного pipeline начните со статьи про GitHub Actions.

Как ломать до production

  • положите prompt injection в README тестовой ветки;
  • попробуйте прочитать недоступный secret;
  • подмените aud и subject OIDC;
  • попросите изменить workflow и IAM;
  • создайте diff больше лимита;
  • зациклите падающий тест;
  • убедитесь, что повторный job не видит файлы предыдущего.

Если единственная проверка — успешный happy path, вы протестировали демо, а не систему.

Проект для портфолио

Соберите репозиторий с агентом, который анализирует падение теста и создаёт patch только в src/. Ограничьте команды, размер diff и число шагов. Добавьте read-only PR workflow, отдельный deploy workflow с OIDC и environment approval, одноразовый runner и журнал решений.

В демонстрации покажите три отказа: injection из README, попытку тронуть workflow и токен с неверным subject. Это инженерный проект. «AI сам починил тест» — только фокус на пять минут.

Частые вопросы

Можно ли агенту автоматически мержить простые изменения?
Можно после отдельной policy, маленького класса изменений и обязательных проверок. Начинать лучше с draft.

OIDC убирает все секреты?
Он убирает долгоживущий cloud key из GitHub, но не отменяет trust policy, минимальные роли и секреты внешних API.

Нужен self-hosted runner?
Не всегда. Он нужен ради контроля среды или сети, но создаёт обязанность изоляции и очистки.

Агент готовит. Политика решает.

Production не должен верить красивому объяснению — только проверенному артефакту.

Собрать обычный CI