Секреты в ресурсах и состоянии, ephemeral-значения

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

Секреты в ресурсах и состоянии, ephemeral-значения

Сообщение 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 и карьера
Представь ситуацию. Ты поднимаешь кластер Managed PostgreSQL в Yandex Cloud через Terraform, задаёшь пароль для пользователя БД, делаешь terraform apply - всё работает. А через неделю выясняется, что пароль от прода лежит открытым текстом в файле terraform.tfstate, который кто-то заботливо закоммитил в git. Поздравляю, у тебя инцидент.

Это не редкость, а почти неизбежность, если работать наивно. Инфраструктура как код (iac) - штука прекрасная, но у Terraform есть одна неприятная особенность: он любит запоминать всё. Любое значение, которое ты передал в ресурс, с высокой вероятностью осядет в state и в плане. В этом уроке разберёмся, как передавать секреты в ресурсы без следов в коде, почему state - это главная дыра, и что подарила нам свежая фича Terraform 1.10/1.11 - ephemeral-значения и write-only атрибуты. Будем гонять на примере пароля для MDB PostgreSQL.

Откуда вообще берутся утечки секретов

Сначала надо понять врага в лицо. У Terraform есть три места, где секрет может засветиться:
  • Сам код (.tf файлы). Если ты пишешь password = "qwerty123" прямо в ресурсе - это самый грубый вариант. Код уходит в репозиторий, и привет.
  • План (terraform plan). Когда ты сохраняешь план в файл через -out, секреты из конфигурации попадают и туда.
  • Состояние (terraform state). Вот это самое коварное. Даже если ты вынес пароль в переменную и нигде его не хардкодишь, после apply финальное значение всё равно записывается в state как факт о созданном ресурсе.
Классический набор приёмов борьбы с первой проблемой ты, скорее всего, уже знаешь. Секрет не пишут в код, а подтягивают со стороны:
  • через переменные окружения - Terraform читает TF_VAR_db_password из окружения, и в коде остаётся только объявление variable;
  • через data source из хранилища секретов (в Yandex Cloud это Lockbox) - пароль лежит в защищённом сервисе, а Terraform забирает его на лету;
  • через зашифрованные файлы (sops, ansible-vault и подобные) - на диске лежит шифротекст, расшифровка происходит в момент прогона.
Всё это хорошо ровно до того момента, пока секрет не доходит до ресурса. А дойдя - оседает в state. И вот тут начинается самое интересное.

Изображение

Почему state - это бомба замедленного действия

Terraform state - это JSON, в котором записано текущее состояние всей твоей инфраструктуры. Зачем он нужен: чтобы Terraform понимал, что уже создано, и не пытался каждый раз пересоздавать ресурсы. Terraform plan и terraform apply сравнивают желаемое состояние из кода с фактическим из state - именно поэтому state обязан хранить реальные значения атрибутов. В том числе пароли.

То есть даже идеально написанный код с переменными окружения и Lockbox не спасает: пароль пользователя кластера всё равно лежит в state открытым текстом. Пометка sensitive = true только прячет значение из вывода в терминал, но в файле оно записано как есть. Это надо твёрдо усвоить: sensitive - это про вывод на экран, а не про шифрование.

Что с этим делать на уровне state (минимальная гигиена, которая нужна всегда):
  • Шифрование бэкенда. Храни state не на ноутбуке, а в удалённом бэкенде с шифрованием. В Yandex Cloud это Object Storage (S3-совместимый бакет) с включённым шифрованием через KMS. Тогда даже сам файл на диске у провайдера лежит зашифрованным.
  • Ограничение доступа. Бакет со state закрывается на отдельную сервисную учётку и узкий круг людей. State - это карта всей инфраструктуры, доступ к нему = доступ ко всем секретам.
  • Никогда не коммить state в git. Звучит банально, но это причина половины инцидентов.
Это правильная защита, но согласись - идея в том, что секрет в state лежит, просто за семью замками. А было бы куда спокойнее, если бы он туда вообще не попадал. И вот в 2026 году у нас наконец есть для этого нормальный инструмент.

Ephemeral-значения и write-only атрибуты (Terraform 1.10/1.11)

В Terraform 1.10 появилась концепция ephemeral - временных значений, которые принципиально не пишутся ни в state, ни в план. Они живут только в оперативной памяти во время прогона и исчезают, как только apply закончился. В 1.11 эту историю докрутили до управляемых ресурсов через write-only аргументы. То же самое доехало и до OpenTofu - открытого форка Terraform, так что фича не привязана к одному вендору.

Из чего это состоит:
  • Ephemeral input variables и outputs. Объявляешь переменную с ephemeral = true, и Terraform гарантирует, что её значение нигде не сохранится.
  • Ephemeral resources. Новый вид блока ephemeral. Вместо привычных Read/Refresh у такого ресурса операции Open и Close: Terraform открывает доступ к секрету, использует его и закрывает. В state не остаётся ничего.
  • Write-only атрибуты. Это аргументы обычных ресурсов, которые можно только записать, но нельзя прочитать обратно. Идеально для паролей: ты передал значение в ресурс, оно ушло в API провайдера - и всё, в state хранится только версия, а не сам пароль.
Покажу базовую механику с ephemeral-переменной. Пароль приходит из окружения, помечается как ephemeral - и не попадает в state:

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

variable "pg_user_password" {
  type      = string
  ephemeral = true
  sensitive = true
}

# в шелле перед прогоном:
# export TF_VAR_pg_user_password='S3cretFromVault!'
Теперь практичный пример с Yandex Lockbox. Секрет с паролем умеет генерироваться прямо в Lockbox - через блок password_payload_specification у ресурса yandex_lockbox_secret. А достаём мы его на лету через data source, причём в идеале значение секрета вообще не должно гулять по state. Сначала создаём секрет с автогенерацией пароля:

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

resource "yandex_lockbox_secret" "pg" {
  name = "pg-app-password"

  password_payload_specification {
    password_key = "password"
    length       = 24
  }
}

resource "yandex_lockbox_secret_version" "pg" {
  secret_id = yandex_lockbox_secret.pg.id
}
Обрати внимание: длина и ключ заданы, а само значение Terraform не выдумывает - его генерирует Lockbox на стороне сервиса. В коде пароля нет вообще.

Теперь собираем сам кластер MDB PostgreSQL. Имена ресурсов и атрибутов - ровно из доки провайдера yandex (yandex_mdb_postgresql_cluster):

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

resource "yandex_mdb_postgresql_cluster" "app" {
  name        = "app-pg"
  environment = "PRODUCTION"
  network_id  = yandex_vpc_network.net.id

  config {
    version = 17
    resources {
      resource_preset_id = "s2.micro"
      disk_type_id       = "network-ssd"
      disk_size          = 16
    }
  }

  host {
    zone      = "ru-central1-d"
    subnet_id = yandex_vpc_subnet.subnet.id
  }
}
А пользователя с паролем заводим отдельным ресурсом - в доке прямо сказано, что user-блок внутри кластера устарел, и пользователей надо вести через yandex_mdb_postgresql_user. Пароль сюда передаём из ephemeral-переменной, чтобы он не осел в state на этапе передачи:

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

resource "yandex_mdb_postgresql_user" "app" {
  cluster_id = yandex_mdb_postgresql_cluster.app.id
  name       = "app"
  password   = var.pg_user_password
  conn_limit = 50
}
Концептуально цель такая: пароль рождается в Lockbox или в окружении, помеченном ephemeral, проходит сквозь конфигурацию и уходит в API Yandex Cloud, ни разу не задержавшись в файле state. Это и есть write-only поведение - значение записали в ресурс, но обратно из state его не вытащить.

Типичные грабли
  • Путать sensitive и ephemeral. sensitive прячет значение из логов, но пишет его в state. ephemeral - не пишет вообще. Это разные вещи, не взаимозаменяемые.
  • Думать, что Lockbox data source решает всё. Обычный (не ephemeral) data source кладёт прочитанное значение в state. То есть подтянул пароль из Lockbox обычным способом - и он снова в state. Спасает именно ephemeral-вариант.
  • Старая версия Terraform. Ephemeral resources требуют 1.10+, write-only аргументы - 1.11+. На 1.5 ничего этого нет, как и в старом OpenTofu. Проверь terraform version перед тем, как закладываться на фичу.
  • Забыть про версионирование write-only. Раз значение нельзя прочитать из state, Terraform не понимает, поменялось ли оно. Чтобы протолкнуть новый пароль, надо менять сопутствующий version-аргумент - иначе обновление просто не триггернётся.
  • Расслабиться по поводу бэкенда. Даже с ephemeral шифрование бэкенда и ограничение доступа к state никто не отменял. Там по-прежнему лежит карта инфраструктуры, пусть и без паролей.
Мини-лаба

Повтори руками, без этого не уляжется:
  • Создай кластер yandex_mdb_postgresql_cluster и пользователя yandex_mdb_postgresql_user с паролем из обычной переменной. Сделай apply.
  • Открой terraform.tfstate и найди в нём свой пароль глазами. Прочувствуй масштаб проблемы.
  • Переделай переменную на ephemeral = true, пересоздай пользователя, снова загляни в state - пароля там уже быть не должно.
  • Заведи yandex_lockbox_secret с password_payload_specification и убедись, что в коде ты пароль не писал ни разу.
  • Настрой удалённый бэкенд в Object Storage с шифрованием и убери локальный state совсем.
Контрольные вопросы
  • Чем отличается sensitive = true от ephemeral = true? Где после apply окажется пароль в каждом случае?
  • Почему обычный data source из Lockbox не спасает пароль от попадания в state, а ephemeral - спасает?
  • Какие минимальные версии Terraform нужны для ephemeral resources и для write-only аргументов?
  • Зачем write-only атрибутам нужен отдельный version-аргумент и что будет, если его не менять?
Итог: что запомнить

Terraform по умолчанию пишет всё в state, и пароль от MDB PostgreSQL там оказывается открытым текстом, даже если ты аккуратно тянул его через переменные окружения или Lockbox. Базовая защита state - шифрование бэкенда и жёсткое ограничение доступа - обязательна всегда. Но с Terraform 1.10/1.11 (и в OpenTofu) появился способ не пускать секрет в state в принципе: ephemeral input variables, ephemeral resources и write-only атрибуты. Пароль проходит сквозь конфигурацию и уходит в API, не оставляя следов в terraform state. Запомни главное правило: sensitive - это про экран, ephemeral - про то, что значения в state не будет вовсе.
👍4 ❤️ 🔥1 😄 🤔
Аватара пользователя
Not1
Сообщения: 1
Зарегистрирован: 27 май 2026, 04:01

Re: Секреты в ресурсах и состоянии, ephemeral-значения

Сообщение Not1 »

Блин, реально открыл свой стейт после прошлого урока - там пароль от прода лежит как есть. Думал sensitive=true меня прикрывает, а оно оказывается только в консоли прячет. Спасибо что разжевали разницу.
👍1 ❤️1 🔥 😄 🤔
Аватара пользователя
K8sCoder
Сообщения: 1
Зарегистрирован: 04 июн 2026, 02:51

Re: Секреты в ресурсах и состоянии, ephemeral-значения

Сообщение K8sCoder »

А если у меня terraform 1.9 на сервере и обновить пока не дают, ephemeral вообще никак не сделать? Или есть какой-то костыль чтобы пароль в стейт не падал на старых версиях?
👍 ❤️ 🔥2 😄 🤔
Ответить
← Предыдущая глава
Аутентификация провайдера и секреты: сервисные аккаунты и OIDC
Следующая глава →
Провайдеры Terraform: установка, версии, required_providers

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

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

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

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

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