Аутентификация провайдера и секреты: сервисные аккаунты и OIDC

Рейтинг: 56.5% · 9 голосов
Подробный курс по Terraform и OpenTofu на примерах Yandex Cloud: ресурсы и провайдеры, состояние и бэкенды, модули, циклы и условия HCL, секреты и Lockbox, тестирование, CI/CD и командная работа. С актуализацией на 2026 (Terraform 1.3-1.10, OpenTofu).
Ответить
Аватара пользователя
Vlad_DevOps
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Аутентификация провайдера и секреты: сервисные аккаунты и OIDC

Сообщение Vlad_DevOps »

Оглавление курса (47)
  1. Что такое инфраструктура как код и зачем она нужна
  2. Категории инструментов IaC: чем отличаются Ansible, Packer, Kubernetes и Terraform
  3. Чем Terraform отличается от Ansible, Pulumi и CloudFormation
  4. Как работает Terraform под капотом и кто такой OpenTofu
  5. Установка Terraform и OpenTofu, подготовка Yandex Cloud
  6. Первый ресурс: разворачиваем виртуальную машину в Yandex Cloud
  7. Веб-сервер на ВМ: метаданные, user-data и группы безопасности
  8. Переменные ввода и выходные значения в Terraform
  9. Кластер ВМ: группа экземпляров Yandex Compute Instance Group
  10. Балансировщик нагрузки: Application Load Balancer в Yandex Cloud
  11. Состояние Terraform: что такое tfstate и чем опасен локальный файл
  12. Удалённое хранилище состояния: бэкенд на Yandex Object Storage
  13. Изоляция состояния: рабочие области против раскладки по папкам
  14. Источники данных и terraform_remote_state: связываем компоненты
  15. Модули Terraform: переиспользуем инфраструктуру
  16. Входные, локальные и выходные переменные модуля
  17. Версионирование модулей и подводные камни
  18. Циклы в Terraform: параметр count
  19. Циклы в Terraform: for_each по множествам и картам
  20. Выражения for и строковые директивы
  21. Условная логика: count-трюк, for_each и директива if
  22. Встроенные функции, типы и выражения HCL
  23. Развёртывание без простоя: create_before_destroy
  24. Подводные камни Terraform и рефакторинг с блоком moved
  25. Управление секретами: основы и типы
  26. Инструменты управления секретами: Yandex Lockbox, Vault, SOPS
  27. Аутентификация провайдера и секреты: сервисные аккаунты и OIDC (вы здесь)
  28. Секреты в ресурсах и состоянии, ephemeral-значения
  29. Провайдеры Terraform: установка, версии, required_providers
  30. Несколько копий одного провайдера: alias и мультизона
  31. Несколько провайдеров и аккаунтов: configuration_aliases
  32. Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud
  33. Код Terraform промышленного уровня: почему это долго
  34. Мелкие компонуемые модули вместо монолита
  35. Тестируемые модули и проверки: validation, precondition, postcondition
  36. Версионирование, публикация модулей и Terragrunt
  37. Ручное тестирование Terraform и очистка ресурсов
  38. Автоматические тесты на Terratest: модульные тесты
  39. Интеграционные и сквозные тесты, пирамида тестирования
  40. Нативный terraform test и статический анализ
  41. Внедрение Terraform в команде: процессы и культура
  42. Конвейер развёртывания прикладного кода
  43. Конвейер инфраструктурного кода и золотое правило Terraform
  44. Стиль, ревью и CI/CD-инструменты: Atlantis, TACOS, policy as code
  45. Что нового в Terraform 1.3-1.10: моды, импорт, провайдер-функции, Stacks
  46. OpenTofu в 2026: чем живёт форк и как мигрировать
  47. Сертификация HashiCorp Terraform Associate и карьера
Представь картину. Ты неделю писал красивый Terraform-код, инфраструктура как код выглядит идеально, ты делаешь terraform plan apply и... провайдер отвечает "permission denied" или того хуже - ты случайно закоммитил файл ключа в git, и теперь у половины интернета есть доступ к твоему облаку. Знакомо? Аутентификация - это та самая скучная тема, на которой спотыкаются и новички, и те, кто "и так все знает". В этом уроке разберем, как Terraform доказывает Yandex Cloud, что он это он, как делать это без единого секрета в коде, и почему в 2026 году долгоживущие ключи в CI - это уже моветон.

Как Terraform вообще логинится в облако

Сам по себе terraform - это просто движок, который читает HCL и дергает API. Чтобы дернуть API Yandex Cloud, ему нужен IAM-токен или эквивалент. Провайдер yandex умеет получать креды из нескольких источников, и порядок тут важен. Грубо говоря, провайдер смотрит:
  • аргументы в блоке provider (token, service_account_key_file) - хардкодить туда секреты НЕ надо;
  • переменные окружения - вот это рабочий вариант;
  • метаданные ВМ (если Terraform крутится на инстансе с привязанным сервисным аккаунтом).
Самый простой способ для человека за ноутбуком - OAuth-токен или IAM-токен через переменную окружения:

Код: Выделить всё

export YC_TOKEN="t1.9eud...."
export YC_CLOUD_ID="b1gxxxxxxxxxxxxxxxxx"
export YC_FOLDER_ID="b1gyyyyyyyyyyyyyyyyy"

terraform plan
Провайдер сам подхватит YC_TOKEN. Минимальный блок провайдера при этом выглядит честно пустым - никаких секретов:

Код: Выделить всё

terraform {
  required_providers {
    yandex = {
      source  = "yandex-cloud/yandex"
      version = ">= 0.130"
    }
  }
}

provider "yandex" {
  # token, cloud_id, folder_id берутся из YC_TOKEN / YC_CLOUD_ID / YC_FOLDER_ID
}
Запомни главное правило: секреты провайдера живут в окружении и в твоей голове, а не в .tf-файлах и не в git. Если ты пишешь token = "t1.9eud..." прямо в конфиге - ты делаешь больно будущему себе.

Изображение

Сервисный аккаунт: робот, который ходит вместо тебя

OAuth-токен человека - это нормально для ручного запуска, но для автоматики (cron, CI, другая инфраструктура) нужен не человек, а робот. В Yandex Cloud такой робот называется сервисный аккаунт. Создается он тем же Terraform:

Код: Выделить всё

resource "yandex_iam_service_account" "tf_runner" {
  name        = "tf-runner"
  description = "service account for terraform automation"
  folder_id   = var.folder_id
}
Обрати внимание на атрибуты из доки провайдера: name, description, folder_id. Поле service_account_id здесь read-only-идентификатор, его руками не задаешь. Сам по себе аккаунт - это пустышка без прав. Чтобы он что-то мог, ему выдают роль. И вот тут вступает принцип наименьших привилегий: не лепи editor или admin на весь folder только потому, что "так проще". Дай ровно то, что нужно задаче.

Код: Выделить всё

resource "yandex_resourcemanager_folder_iam_member" "tf_runner_compute" {
  folder_id = var.folder_id
  role      = "compute.editor"
  member    = "serviceAccount:${yandex_iam_service_account.tf_runner.id}"
}
Формат member тут строгий - serviceAccount:{id}, именно так провайдер понимает, кому давать роль. На каждую роль - отдельный ресурс iam_member, не пытайся запихнуть список ролей в один блок.

Дальше классика - аккаунту нужен ключ, чтобы Terraform мог под ним аутентифицироваться. Авторизованный ключ (тот самый JSON) обычно создают через yc CLI или ресурс yandex_iam_service_account_key, а Terraform указывают на файл через переменную окружения:

Код: Выделить всё

# создаем ключ один раз через CLI
yc iam key create --service-account-name tf-runner --output key.json

export YC_SERVICE_ACCOUNT_KEY_FILE="/secure/path/key.json"
terraform apply
Файл key.json - это, по сути, пароль от твоего облака в виде приватного RSA-ключа. Хранить его надо как пароль: в Lockbox, в Vault, в защищенном секрет-сторадже CI, но не в репозитории и не в Telegram-чате "на минутку".

Статический ключ для Object Storage - отдельная история

Тут есть тонкость, на которой спотыкаются почти все. Object Storage в Yandex Cloud - это S3-совместимое хранилище, и оно ходит не по IAM-токену, а по паре access_key/secret_key в стиле AWS. Для этого есть отдельный ресурс:

Код: Выделить всё

resource "yandex_iam_service_account_static_access_key" "storage_key" {
  service_account_id = yandex_iam_service_account.tf_runner.id
  description        = "static access key for object storage"
}

output "access_key" {
  value = yandex_iam_service_account_static_access_key.storage_key.access_key
}

output "secret_key" {
  value     = yandex_iam_service_account_static_access_key.storage_key.secret_key
  sensitive = true
}
Атрибуты строго из доки: на входе обязателен service_account_id, на выходе read-only access_key и secret_key (secret_key возвращается, только если ты не используешь pgp_key или output_to_lockbox). Заметь sensitive = true у secret_key - иначе Terraform радостно напечатает его в лог. И помни: этот ключ попадет в terraform state в открытом виде, так что твой state-файл сам по себе становится секретом. Поэтому terraform state должен лежать в зашифрованном бэкенде (например, в том же Object Storage с шифрованием), а не валяться локально в репо.

Для совсем взрослого подхода у ресурса есть блок output_to_lockbox - тогда secret_key не светится в state, а сразу уезжает в секрет Lockbox с полями entry_for_access_key и entry_for_secret_key.

2026: OIDC-федерация - убиваем долгоживущие ключи в CI

Теперь главный апгрейд. Любой ключ-файл - это бомба замедленного действия: он не протухает сам, его надо ротировать, его могут украсть. Для CI вроде GitHub Actions или GitLab правильный путь в 2026 году - workload identity federation по протоколу OIDC. Идея гениальна в своей простоте: пайплайн получает короткоживущий OIDC-токен от своего провайдера (GitHub, GitLab), Yandex Cloud этому токену доверяет и обменивает его на временный IAM-токен. Никаких файлов ключей в секретах CI вообще.

Настраивается это двумя ресурсами. Сначала федерация - доверие к внешнему IdP:

Код: Выделить всё

resource "yandex_iam_workload_identity_oidc_federation" "github" {
  name      = "github-actions-federation"
  folder_id = var.folder_id
  disabled  = false
  audiences = ["https://github.com/my-org"]
  issuer    = "https://token.actions.githubusercontent.com"
  jwks_url  = "https://token.actions.githubusercontent.com/.well-known/jwks"
}
Здесь все атрибуты реальны: audiences - список доверенных значений aud, issuer - URL внешнего IdP (для GitHub Actions это token.actions.githubusercontent.com), jwks_url - адрес публичных ключей для проверки подписи токена, disabled - выключатель.

Дальше привязываем конкретный внешний субъект (репозиторий, ветку, окружение) к сервисному аккаунту через федеративную привязку:

Код: Выделить всё

resource "yandex_iam_workload_identity_federated_credential" "github_main" {
  service_account_id  = yandex_iam_service_account.tf_runner.id
  federation_id       = yandex_iam_workload_identity_oidc_federation.github.id
  external_subject_id = "repo:my-org/my-repo:ref:refs/heads/main"
}
external_subject_id - это значение sub из OIDC-токена. Так ты говоришь: "именно ветка main именно этого репозитория может действовать от имени tf-runner". Не вся организация, не любой форк - конкретный субъект. Снова тот же принцип наименьших привилегий, но уже на уровне аутентификации.

Кстати, все ровно это работает и в OpenTofu - открытом форке Terraform под лицензией MPL 2.0 (на середину 2026 актуальна ветка 1.x). Провайдер yandex один и тот же, синтаксис HCL идентичен, так что выбор движка на тему секретов не влияет.

Типичные грабли
  • Секрет в коде. token = "t1...." или путь к key.json прямо в provider. Закоммитил - считай, утек. Чисти историю git и отзывай ключ.
  • Слишком жирная роль. admin на folder "чтобы работало". Работает, да. И весь твой CI теперь может удалить вообще все. Дай compute.editor, vpc.admin - что реально нужно.
  • Забыл sensitive у secret_key. Terraform печатает секрет в plan/apply, а лог CI хранится публично. Прощай, секрет.
  • Незащищенный terraform state. Статические ключи и пароли лежат в state открытым текстом. Локальный state в репозитории - это утечка.
  • Слишком широкий external_subject_id в OIDC. Если разрешишь любой репозиторий org - чужой форк сможет угнать твой сервисный аккаунт. Привязывай к конкретной ветке/окружению.
Мини-лаба

Повтори руками, без этого в голове не уляжется:
  • Подними YC_TOKEN/YC_CLOUD_ID/YC_FOLDER_ID через export и сделай terraform plan с пустым блоком provider. Убедись, что секретов в коде ноль.
  • Опиши yandex_iam_service_account и выдай ему ОДНУ узкую роль через yandex_resourcemanager_folder_iam_member.
  • Создай yandex_iam_service_account_static_access_key, выведи secret_key с sensitive = true и убедись, что в логе apply его не видно, а в state - видно (открой state и ужаснись).
  • Опиши федерацию yandex_iam_workload_identity_oidc_federation для GitHub Actions и привяжи к ней federated_credential на ветку main. Сравни, насколько это спокойнее, чем хранить key.json в секретах репозитория.
Контрольные вопросы
  • Какие переменные окружения подхватывает провайдер yandex для аутентификации и зачем держать секреты именно там, а не в HCL?
  • Чем статический ключ для Object Storage отличается от авторизованного ключа сервисного аккаунта и почему secret_key надо помечать sensitive?
  • Какие два ресурса нужны, чтобы настроить OIDC-федерацию для GitHub Actions, и что задает external_subject_id?
  • Почему долгоживущий key.json в секретах CI хуже, чем workload identity federation?
Итог: что запомнить

Аутентификация - это фундамент безопасности всей твоей инфраструктуры как код. Секреты провайдера живут в переменных окружения и секрет-хранилищах, а не в git. Для автоматики заводи сервисный аккаунт и давай ему минимум прав. Object Storage ходит по отдельному статическому ключу, который утекает в terraform state, поэтому state шифруй. А для CI в 2026 году забудь про файлы ключей: OIDC-федерация (yandex_iam_workload_identity_oidc_federation плюс federated_credential) дает короткоживущие токены без единого долгоживущего секрета. Меньше ключей - меньше поводов для бессонницы.
👍2 ❤️2 🔥 😄 🤔
Аватара пользователя
kernelenjoyer
Сообщения: 1
Зарегистрирован: 28 май 2026, 01:07

Re: Аутентификация провайдера и секреты: сервисные аккаунты и OIDC

Сообщение kernelenjoyer »

Спасибо, наконец дошло зачем нужен static_access_key отдельно. Я раньше пихал YC_TOKEN везде и удивлялся почему бакеты не читаются, а оно вон как - S3 хочет свою пару ключей.
👍1 ❤️ 🔥 😄 🤔1
Аватара пользователя
khp1016
Сообщения: 1
Зарегистрирован: 22 май 2026, 13:20

Re: Аутентификация провайдера и секреты: сервисные аккаунты и OIDC

Сообщение khp1016 »

А вопрос по OIDC: если у меня монорепо и деплоят несколько веток, мне на каждую ветку делать свой federated_credential или можно как-то wildcard в external_subject_id? Боюсь дать слишком широкий доступ.
👍3 ❤️1 🔥 😄 🤔
Ответить
← Предыдущая глава
Инструменты управления секретами: Yandex Lockbox, Vault, SOPS
Следующая глава →
Секреты в ресурсах и состоянии, ephemeral-значения

Все главы курса «Terraform: инфраструктура как код на Yandex Cloud»

Поделиться темой: ✈ Telegram VK
  • Похожие темы
Похожие запросы: управление секретами в terraform yandex lockbox

Вернуться в «Terraform: инфраструктура как код на Yandex Cloud»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость