Dev48
ЯЗЫК
  • О нас
  • Услуги
  • Индустрии
  • Технологии
  • Статьи
  • Контакты
Забронировать звонок
    Главная/Статьи/Upravlenie sekretami v vashem kode terraform
Dev48

© 2026 · All rights reserved.

Управление секретами в вашем коде Terraform

Источник: Gruntwork

Управление секретами в вашем коде Terraform

Источник: Gruntwork

Управление секретами в коде Terraform: работа с паролями и ключами API с помощью переменных окружения, зашифрованных файлов (таких как KMS и SOPS) и хранилищ секретов вроде Vault.

25 сентября 2026 г.

Один из самых частых вопросов, которые нам задают по поводу использования Terraform для управления инфраструктурой как кодом, — это как обращаться с секретами, такими как пароли, ключи API и другие конфиденциальные данные. Например, вот фрагмент кода Terraform, который можно использовать для развертывания MySQL с помощью Amazon RDS:

Обратите внимание, что Terraform требует указать два секрета — имя пользователя (username) и пароль (password), которые являются учетными данными для главного пользователя базы данных. В этой статье я рассмотрю наиболее распространенные методы безопасного управления такими секретами:

  • Предварительное условие №1: Не храните секреты в открытом виде
  • Предварительное условие №2: Обеспечьте безопасность состояния Terraform
  • Метод №1: Переменные окружения
  • Метод №2: Зашифрованные файлы (например, KMS, PGP, SOPS)
  • Метод №3: Хранилища секретов (например, Vault, AWS Secrets Manager)

Предварительное условие №1: Не храните секреты в открытом виде

Первое правило управления секретами гласит:

Не храните секреты в открытом виде.

Второе правило управления секретами гласит:

НЕ ХРАНИТЕ СЕКРЕТЫ В ОТКРЫТОМ ВИДЕ.

Серьезно, не делайте этого. Например, НЕ зашивайте учетные данные базы данных прямо в код Terraform и не добавляйте их в систему контроля версий:

Хранение секретов в открытом виде в системе контроля версий — ПЛОХАЯ ИДЕЯ. Вот лишь несколько причин почему:

  • Любой, у кого есть доступ к системе контроля версий, имеет доступ к этому секрету. В примере выше каждый разработчик в вашей компании имеет доступ к главным учетным данным вашей базы данных.
  • Каждый компьютер, имеющий доступ к системе контроля версий, хранит копию этого секрета. На каждом компьютере, когда-либо склонировавшем этот репозиторий, все еще может оставаться копия этого секрета на локальном жестком диске. Сюда относятся компьютеры всех разработчиков в вашей команде, все компьютеры, задействованные в CI (например, Jenkins, CircleCI, GitLab и т.д.), все компьютеры системы контроля версий (GitHub, GitLab, BitBucket), все компьютеры, задействованные в развертывании (все ваши среды pre-prod и prod), все компьютеры для резервного копирования (CrashPlan, Time Machine и т.д.) и так далее.
  • Любое запущенное вами программное обеспечение имеет доступ к этому секрету. Поскольку секреты хранятся в открытом виде на таком количестве жестких дисков, любая программа, работающая на любом из этих компьютеров, потенциально может прочитать этот секрет.
  • Отсутствует способ аудита или отзыва доступа к этому секрету. Когда секреты хранятся на сотнях жестких дисков в открытом виде, вы не можете узнать, кто к ним обращался (нет журнала аудита), и не можете отозвать доступ.

Короче говоря, если вы храните секреты в открытом виде, вы даете злоумышленникам (хакерам, конкурентам, недовольным бывшим сотрудникам) бесчисленные способы получить доступ к самым конфиденциальным данным вашей компании — например, путем компрометации системы контроля версий, любого из ваших компьютеров или любой программы на них, — и вы даже не узнаете о взломе и не сможете легко все исправить.

Поэтому я настоятельно рекомендую всегда хранить секреты в зашифрованном виде. Это относится ко всем секретам, а не только к тем, что используются с Terraform! Далее в этой статье я расскажу о нескольких различных методах шифрования и дешифрования таких секретов.

Предварительное условие №2: Обеспечьте безопасность состояния Terraform

Будем надеяться, что предыдущий раздел убедил вас не хранить секреты в открытом виде, а следующие разделы покажут вам несколько методов шифрования секретов. Однако независимо от выбранного метода шифрования с вашей стороны, есть одно место, где они все равно окажутся в открытом виде: состояние Terraform.

Каждый раз, когда вы развертываете инфраструктуру с помощью Terraform, она сохраняет множество данных об этой инфраструктуре, включая все переданные вами параметры, в файл состояния. По умолчанию это файл terraform.tfstate, который автоматически создается в папке, где вы выполнили команду terraform apply. Так что даже если вы используете один из упомянутых ниже безопасных способов передачи секретов (например, учетных данных базы данных):

Эти секреты все равно попадут в terraform.tfstate в открытом виде! Эта проблема остается открытой уже более 6 лет, и четких планов по ее решению на уровне самого инструмента пока нет. Существуют обходные пути, позволяющие удалять секреты из файлов состояния, но они ненадежны и могут сломаться при любом новом релизе Terraform, поэтому я их не рекомендую.

В настоящее время, независимо от того, какой из описанных ниже методов вы решите использовать для управления секретами, вы также должны:

  • Хранить состояние Terraform в бэкенде, поддерживающем шифрование. Вместо хранения состояния в локальном файле terraform.tfstate, Terraform из коробки поддерживает различные бэкенды, такие как S3, GCS и Azure Blob Storage. Многие из этих бэкендов поддерживают шифрование, поэтому файлы состояния никогда не будут храниться в открытом виде: они всегда зашифрованы как при передаче (например, по протоколу TLS), так и на диске (например, с помощью AES-256). Большинство бэкендов также поддерживают функции совместной работы (например, автоматическую отправку и получение состояния, блокировку), поэтому использование бэкенда является обязательным с точки зрения безопасности и командной работы. Дополнительную информацию см. в разделе «Как управлять состоянием Terraform».
  • Строго контролировать доступ к вашему бэкенду Terraform. Поскольку файлы состояния Terraform могут содержать секреты, вам нужно тщательно контролировать, у кого есть доступ к бэкенду, используемому для хранения этих файлов. Например, если вы используете S3 в качестве бэкенда, вам следует настроить политику IAM, которая разрешает доступ к S3-бакету для продакшна только небольшой группе доверенных разработчиков (или исключительно CI-серверу, используемому для деплоя в продакшн).

А теперь, без лишних слов, давайте обсудим различные методы управления секретами с помощью Terraform.

Метод №1: Переменные окружения

Этот первый метод защищает ваш код от секретов в открытом виде за счет использования встроенной поддержки чтения переменных окружения в Terraform.

Обзор

Чтобы использовать этот метод, объявите переменные для секретов, которые хотите передать:

Обновление от 3 декабря 2020 г.: В Terraform 0.14 появилась возможность помечать переменные как чувствительные (sensitive), что помогает скрывать их в логах, поэтому вам следует добавить sensitive = true для обеих переменных выше!

Затем передайте переменные ресурсам Terraform, которым нужны эти секреты:

Теперь вы можете передать значение для каждой переменной foo, установив переменную окружения с именем TF_VAR_foo. Например, вот как вы можете задать имя пользователя и пароль через окружение в Linux, Unix или Mac, а затем запустить terraform apply для развертывания базы данных:

(Полезный совет: если у вас правильно настроена переменная окружения HISTCONTROL в терминале Bash, любая команда, начинающаяся с пробела, не будет сохраняться в истории Bash. Используйте это при установке переменных окружения с секретами, чтобы избежать сохранения этих секретов на диске).

Эта техника помогает избежать хранения секретов в виде простого текста в коде, но оставляет открытым вопрос о том, как на самом деле безопасно хранить секреты и управлять ими. Так что в определенном смысле этот подход лишь откладывает проблему на потом, в то время как другие методы, описанные далее в этой статье, являются более конкретными.

Тем не менее, чтобы не оставлять вас в неведении: если вы все же решите использовать переменные окружения, самым распространенным решением для хранения секретов и управления ими является использование менеджера паролей, например:

  • 1Password: SaaS-инструмент, который предлагает (а) настольные и мобильные приложения для всех платформ и (b) облачную синхронизацию, позволяющую получить доступ к вашим секретам на всех устройствах и работать в команде.
  • LastPass: SaaS-инструмент, который предлагает (а) настольные и мобильные приложения для всех платформ и (b) облачную синхронизацию, позволяющую получить доступ к вашим секретам на всех устройствах и работать в команде.
  • pass: Инструмент с открытым исходным кодом, следующий философии Unix: это инструмент командной строки, он выполняет ввод и вывод через текстовые потоки (т.е. stdin, stdout), а под капотом хранит все в виде файлов, причем каждый секрет находится в собственном файле, зашифрованном с помощью PGP (эти зашифрованные файлы можно добавлять в систему контроля версий для командной работы).

Эти инструменты решают проблему «откладывания на потом», полагаясь на человеческую память: то есть на вашу способность запомнить пароль, который дает вам доступ к менеджеру паролей.

Пример использования pass

Давайте рассмотрим быстрый пример использования pass. Сначала вам нужно сохранить секреты с помощью команды pass insert:

Вы можете вывести секрет в stdout, запустив pass <secret>:

Вы можете использовать эту функциональность в субшелле, чтобы установить секреты в качестве переменных окружения, а затем вызвать terraform apply:

Преимущества этого подхода

  • Секреты в виде простого текста не попадают в ваш код и систему контроля версий.
  • Простое решение для начала работы.
  • Интеграция с большинством других решений для управления секретами: например, если у вашей компании уже есть способ управления секретами, вы обычно можете заставить его работать с переменными окружения.
  • Удобно для тестирования: при написании тестов для вашего кода Terraform (например, с помощью Terratest) не нужно настраивать зависимости (например, хранилища секретов), так как вы можете легко установить переменные окружения в фиктивные значения.

Недостатки этого подхода

  • Не все определено в самом коде Terraform. Это усложняет понимание и поддержку кода.
  • Каждый, кто использует ваш код, должен знать о необходимости совершения дополнительных шагов: либо вручную задавать эти переменные окружения, либо запускать вспомогательный скрипт.
  • Никаких гарантий или мнений относительно безопасности. Поскольку управление всеми секретами происходит за пределами Terraform, код не обеспечивает соблюдение каких-либо свойств безопасности, и вполне возможно, что кто-то все еще управляет секретами небезопасным способом (например, хранит их в виде простого текста).

Техника № 2: Зашифрованные файлы (например, KMS, PGP, SOPS)

Второй подход заключается в шифровании секретов, сохранении зашифрованного текста в файл и добавлении этого файла в систему контроля версий.

Обзор

Чтобы зашифровать некоторые данные, например секреты в файле, вам нужен ключ шифрования. Этот ключ сам по себе является секретом! Это создает определенную дилемму: как безопасно хранить этот ключ? Вы не можете добавить ключ в систему контроля версий в виде простого текста, иначе шифрование чего-либо с его помощью теряет смысл. Вы можете зашифровать ключ другим ключом, но тогда вам придется выяснить, где хранить этот второй ключ. Так что вы возвращаетесь к проблеме «откладывания на потом», поскольку вам все равно нужно найти безопасный способ хранения ключа шифрования.

Наиболее распространенным решением этой дилеммы является хранение ключа в службе ключей, предоставляемой вашим облачным провайдером, такой как:

  • AWS KMS
  • GCP KMS
  • Azure Key Vault

Эти службы ключей решают проблему «откладывания на потом», полагаясь на человеческую память: в данном случае на вашу способность запомнить пароль, который дает вам доступ к вашему облачному провайдеру (или, возможно, вы храните этот пароль в менеджере паролей и вместо этого запоминаете пароль от него).

Пример использования AWS KMS

Вот пример того, как можно использовать ключ, управляемый AWS KMS, для шифрования секретов. Сначала создайте файл db-creds.yml с вашими секретами:

Примечание: НЕ добавляйте этот файл в систему контроля версий!

Затем зашифруйте этот файл с помощью команды aws kms encrypt и запишите полученный зашифрованный текст в файл db-creds.yml.encrypted:

Теперь вы можете безопасно добавить db-creds.yml.encrypted в систему контроля версий.

Чтобы расшифровать секреты из этого файла в вашем коде Terraform, вы можете использовать источник данных aws_kms_secrets (для GCP KMS или Azure Key Vault вместо этого используются источники данных google_kms_secret или azurerm_key_vault_secret соответственно):

Приведенный выше код прочитает db-creds.yml.encrypted с диска и, при условии наличия у вас прав на доступ к соответствующему ключу в KMS, расшифрует содержимое для получения исходного YAML. Вы можете разобрать YAML следующим образом:

И теперь вы можете прочитать имя пользователя и пароль из этого YAML и передать их в ресурс aws_db_instance:

Одна из проблем такого подхода заключается в том, что работать с зашифрованными файлами неудобно. Чтобы внести изменения, вам нужно локально расшифровать файл с помощью длинной команды aws kms decrypt, внести изменения, снова зашифровать файл с помощью другой длинной команды aws kms encrypt и все это время быть предельно осторожным, чтобы случайно не добавить незашифрованные данные в систему контроля версий и не оставить их навсегда на своем компьютере. Это утомительный и подверженный ошибкам процесс, если только вы не используете такой инструмент, как sops.

Пример использования AWS KMS с sops и Terragrunt

sops — это инструмент с открытым исходным кодом, разработанный для упрощения редактирования и работы с файлами, зашифрованными с помощью AWS KMS, GCP KMS, Azure Key Vault или PGP. sops может автоматически расшифровывать файл при его открытии в текстовом редакторе, поэтому вы можете редактировать файл в виде простого текста, а при сохранении этих файлов он автоматически снова шифрует содержимое. Это избавляет от необходимости запускать длинные команды aws kms для шифрования или расшифровки данных, а также от беспокойства о том, что секреты в виде простого текста будут случайно добавлены в систему контроля версий. Вот .gif, показывающий sops в действии:

Terraform пока не имеет встроенной поддержки расшифровки файлов в формате, используемом sops. Одним из решений является установка и использование пользовательского провайдера для sops — terraform-provider-sops. Другой вариант, который я продемонстрирую здесь, — использование Terragrunt, в который встроена нативная поддержка sops. Terragrunt — это тонкая обертка над Terraform, которая помогает поддерживать ваш код Terraform в DRY-состоянии и пригодным для поддержки (ознакомьтесь с руководством по быстрому старту для получения общего представления).

Допустим, вы использовали sops для создания зашифрованного файла YAML с именем db-creds.yml, как показано на .gif выше. Теперь в вашей конфигурации terragrunt.hcl вы можете использовать встроенную в Terragrunt функцию sops_decrypt_file для расшифровки этого файла и yamldecode для его разбора как YAML:

Затем вы можете передать имя пользователя и пароль в качестве входных данных в ваш код Terraform:

Ваш код Terraform, в свою очередь, может читать эти входные данные через переменные:

Обновление от 3 декабря 2020 г.: в Terraform 0.14 добавлена возможность помечать переменные как конфиденциальные (sensitive), что помогает не допускать их попадания в логи, поэтому вам следует добавить sensitive = true к обеим переменным выше!

И передайте эти переменные в aws_db_instance:

Преимущества этого метода

  • Храните секреты в виде открытого текста вне вашего кода и системы контроля версий.
  • Ваши секреты хранятся в зашифрованном виде в системе контроля версий, поэтому они версионируются, упаковываются и тестируются вместе с остальным вашим кодом. Это помогает уменьшить количество ошибок конфигурации, например, когда вы добавляете новый секрет в одном окружении (например, staging), но забываете добавить его в другом (например, production).
  • Работает с различными вариантами шифрования: AWS KMS, GCP KMS, PGP и т. д.
  • Все описано в коде. Не требуется никаких дополнительных ручных шагов или сценариев-оберток (хотя интеграция sops требует либо пользовательского провайдера, либо вспомогательного инструмента, такого как Terragrunt).

Недостатки этого метода

  • Шифрование данных требует дополнительных усилий. Вам приходится либо выполнять множество команд (например, aws kms encrypt), либо использовать внешний инструмент, такой как sops. Существует кривая обучения для правильного и безопасного использования этих инструментов.
  • Секреты теперь зашифрованы, но поскольку они по-прежнему хранятся в системе контроля версий, их ротация и отмена затруднены. Если кто-то когда-либо скомпрометирует ключ шифрования, он сможет вернуться назад и расшифровать все секреты, которые когда-либо были им зашифрованы.
  • Возможность аудита того, кто получал доступ к секретам, минимальна. Если вы используете облачную систему управления ключами (например, AWS KMS), она, скорее всего, ведет журнал аудита того, кто использовал ключ для расшифровки чего-либо, но вы не сможете узнать, что именно было расшифровано.
  • Менее удобно для тестирования: при написании тестов для вашего кода Terraform (например, с помощью Terratest) вам придется выполнять дополнительную работу по шифрованию данных для ваших тестовых окружений.
  • Большинство управляемых сервисов ключей стоят небольших денег. Например, каждый ключ, который вы храните в AWS KMS, стоит $1 в месяц.

Метод № 3: Хранилища секретов (например, Vault, AWS Secrets Manager)

Третий метод заключается в хранении секретов в выделенном хранилище секретов: то есть в базе данных, которая специально разработана для безопасного хранения конфиденциальных данных и жесткого контроля доступа к ним.

Обзор

Вот несколько более популярных хранилищ секретов, которые вы можете рассмотреть:

  • HashiCorp Vault: кроссплатформенное хранилище секретов с открытым исходным кодом.
  • AWS Secrets Manager: управляемое AWS хранилище секретов.
  • AWS Param Store: управляемое AWS хранилище данных с поддержкой шифрования.
  • GCP Secret Manager: управляемое GCP хранилище ключей/значений.

Эти хранилища секретов решают проблему «откладывания на потом», полагаясь на человеческую память: в данном случае на вашу способность запомнить пароль, который дает вам доступ к вашему облачному провайдеру (или несколько паролей в случае Vault, так как он использует разделение секрета Шамира).

Пример использования AWS Secrets Manager

Сначала войдите в пользовательский интерфейс AWS Secrets Manager, нажмите «store a new secret» и введите секреты, которые вы хотите сохранить:

По умолчанию используется формат JSON, как вы можете видеть на скриншоте выше. Затем дайте секрету уникальное имя:

Нажмите «next» и «store», чтобы сохранить секрет.

Теперь в своем коде Terraform вы можете использовать источник данных aws_secretsmanager_secret_version для чтения этого секрета (для HashiCorp Vault, AWS SSM Param Store или GCP Secret Store вместо этого вы будете использовать источник данных vault_generic_secret, aws_ssm_parameter или google_secret_manager_secret_version):

Если вы сохранили секретные данные в формате JSON, вы можете использовать jsondecode для их синтаксического анализа:

И теперь вы можете использовать эти секреты в остальной части вашего кода Terraform:

Преимущества этого метода

  • Храните секреты в виде открытого текста вне вашего кода и системы контроля версий.
  • Ваши секреты хранятся в специальном хранилище секретов, которое обеспечивает шифрование и строгий контроль доступа.
  • Все определено в самом коде. Не требуется никаких дополнительных ручных шагов или сценариев-оберток.
  • Использование веб-интерфейса для хранения секретов обеспечивает удобство работы с минимальной кривой обучения.
  • Хранилища секретов обычно поддерживают ротацию секретов, что полезно в случае компрометации секрета. Вы даже можете включить ротацию по расписанию (например, каждые 30 дней) в качестве превентивной меры.
  • Хранилища секретов обычно поддерживают подробные журналы аудита, которые показывают вам, кто именно и к каким данным получил доступ.
  • Хранилища секретов обычно предоставляют API, который можно легко использовать из всех ваших приложений, а не только из кода Terraform. AWS Secrets Manager даже генерирует фрагменты кода, которые показывают вам, как именно читать ваши секреты из приложений, написанных на Java, Python, JavaScript, Ruby, Go и т. д.:

Недостатки этого метода

  • Поскольку секреты не версионируются, не упаковываются и не тестируются вместе с вашим кодом, более вероятны ошибки конфигурации, такие как добавление нового секрета в одном окружении (например, staging), но забывание добавить его в другом (например, production).
  • Большинство управляемых хранилищ секретов стоят денег. Например, AWS Secrets Manager взимает 0,40 доллара в месяц за каждый хранимый секрет плюс 0,05 доллара за каждые 10 000 вызовов API, которые вы делаете для сохранения или извлечения данных.
  • Если вы используете хранилище секретов, управляемое самостоятельно, например HashiCorp Vault, вы тратите как деньги на запуск хранилища (например, платите AWS за 3–5 инстансов EC2 для запуска Vault в режиме высокой доступности), так и время и деньги на то, чтобы ваша команда развертывала, настраивала, управляла, обновляла и мониторила хранилище.
  • Менее удобно для тестирования: при написании тестов для вашего кода Terraform (например, с помощью Terratest) вам придется выполнять дополнительную работу по записи данных в хранилища секретов.

Заключение

Вот основные выводы из этой публикации в блоге:

  • Не храните секреты в виде обычного текста.
  • Используйте бэкенд Terraform, поддерживающий шифрование.
  • Используйте переменные окружения, зашифрованные файлы или хранилище секретов для безопасной передачи секретов в ваш код Terraform. См. таблицу ниже для сравнения преимуществ и недостатков этих вариантов.

Вся ваша инфраструктура. Определенная как код. Примерно за день. Gruntwork.io.

← Все статьи