HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Когда мы работаем с проектом через Terraform, важно сохранять в безопасности чувствительные данные. Для этого в Terraform есть секреты.</p>
1 <p>Когда мы работаем с проектом через Terraform, важно сохранять в безопасности чувствительные данные. Для этого в Terraform есть секреты.</p>
2 <p>В этом уроке мы научимся использовать и хранить секреты, чтобы получить контроль над доступом к чувствительным данным и снизить риск их утечки.</p>
2 <p>В этом уроке мы научимся использовать и хранить секреты, чтобы получить контроль над доступом к чувствительным данным и снизить риск их утечки.</p>
3 <p>В каждом проекте есть данные, которыми не стоит делиться с посторонними, например: токены, пароли, API-ключи для интеграций с другими сервисами. Их не следует хранить в коде в открытом виде.</p>
3 <p>В каждом проекте есть данные, которыми не стоит делиться с посторонними, например: токены, пароли, API-ключи для интеграций с другими сервисами. Их не следует хранить в коде в открытом виде.</p>
4 <p>Такие чувствительные данные в Terraform называются<strong>секретами</strong>.</p>
4 <p>Такие чувствительные данные в Terraform называются<strong>секретами</strong>.</p>
5 <p>Terraform позволяет использовать для хранения секретов:</p>
5 <p>Terraform позволяет использовать для хранения секретов:</p>
6 <ul><li>Переменные окружения</li>
6 <ul><li>Переменные окружения</li>
7 <li>Локальные файлы</li>
7 <li>Локальные файлы</li>
8 <li>Удаленные key-value хранилища: Hashicorp Vault или Yandex Lockbox</li>
8 <li>Удаленные key-value хранилища: Hashicorp Vault или Yandex Lockbox</li>
9 </ul><p>Рассмотрим пример файла с переменными Terraform, в котором мы описываем инфрастуктуру:</p>
9 </ul><p>Рассмотрим пример файла с переменными Terraform, в котором мы описываем инфрастуктуру:</p>
10 <p>Обычно такую информацию посторонний не сможет использовать нам во вред, даже если мы будем хранить ее в открытом виде.</p>
10 <p>Обычно такую информацию посторонний не сможет использовать нам во вред, даже если мы будем хранить ее в открытом виде.</p>
11 <p>Теперь добавим в файл значения с чувствительными данными:</p>
11 <p>Теперь добавим в файл значения с чувствительными данными:</p>
12 <p>Если запушить такой файл в удаленный репозиторий, это сделает инфрастуктуру уязвимой.</p>
12 <p>Если запушить такой файл в удаленный репозиторий, это сделает инфрастуктуру уязвимой.</p>
13 <p>Любой человек, у которого есть доступ к этому репозиторию, сможет подключиться к нашему облаку и выполнить с ресурсами любые действия. Например, можно подложить свои ключи для авторизации на наши машины или извлечь ценные данные из базы.</p>
13 <p>Любой человек, у которого есть доступ к этому репозиторию, сможет подключиться к нашему облаку и выполнить с ресурсами любые действия. Например, можно подложить свои ключи для авторизации на наши машины или извлечь ценные данные из базы.</p>
14 <p>Чтобы избежать таких проблем, нужно научиться хранить и управлять секретами. Начнем с объявления секретных переменных.</p>
14 <p>Чтобы избежать таких проблем, нужно научиться хранить и управлять секретами. Начнем с объявления секретных переменных.</p>
15 <h2>Как объявить секретные переменные</h2>
15 <h2>Как объявить секретные переменные</h2>
16 <p>Когда мы объявляем секретные переменные, нужно минимизировать их появление в явном виде при выполнении команд. Для этого в Terraform используют параметр sensitive = true:</p>
16 <p>Когда мы объявляем секретные переменные, нужно минимизировать их появление в явном виде при выполнении команд. Для этого в Terraform используют параметр sensitive = true:</p>
17 <p>Это параметр задается для секретной переменной и скрывает значение переменной при выполнении terraform apply / terraform plan.</p>
17 <p>Это параметр задается для секретной переменной и скрывает значение переменной при выполнении terraform apply / terraform plan.</p>
18 <p>Когда выполняется terraform apply, передаваемая ресурсу переменная с паролем скрывается:</p>
18 <p>Когда выполняется terraform apply, передаваемая ресурсу переменная с паролем скрывается:</p>
19 <p>Поля, которые определяются с применением секретных переменных, будут показаны в выводе terraform как (sensitive value).</p>
19 <p>Поля, которые определяются с применением секретных переменных, будут показаны в выводе terraform как (sensitive value).</p>
20 <p>Мы корректно объявили все секретные переменные. Теперь нужно выбрать подходящее решение, чтобы передать эти переменные в инфраструктуру.</p>
20 <p>Мы корректно объявили все секретные переменные. Теперь нужно выбрать подходящее решение, чтобы передать эти переменные в инфраструктуру.</p>
21 <h2>Как передавать секреты в инфраструктуру</h2>
21 <h2>Как передавать секреты в инфраструктуру</h2>
22 <p>По умолчанию Terraform позволяет передавать секреты интерактивно. Если Terraform видит объявленную переменную, но не знает ее значения, при выполнении terraform apply он попробует узнать значение у нас:</p>
22 <p>По умолчанию Terraform позволяет передавать секреты интерактивно. Если Terraform видит объявленную переменную, но не знает ее значения, при выполнении terraform apply он попробует узнать значение у нас:</p>
23 <p>Например, мы можем ввести значение yc_iam_token в момент развертывания инфраструктуры.</p>
23 <p>Например, мы можем ввести значение yc_iam_token в момент развертывания инфраструктуры.</p>
24 <p>Так можно не фиксировать секретные значения в проекте, а только объявлять переменные и вводить их вручную по факту выполнения terraform apply:</p>
24 <p>Так можно не фиксировать секретные значения в проекте, а только объявлять переменные и вводить их вручную по факту выполнения terraform apply:</p>
25 <p>Это безопасный способ, но затратный по времени и силам, так как все секреты нужно вводить поочередно при выполнении любой операции Terraform. Также такой способ не подходит для автоматизации работы с инфраструктурой.</p>
25 <p>Это безопасный способ, но затратный по времени и силам, так как все секреты нужно вводить поочередно при выполнении любой операции Terraform. Также такой способ не подходит для автоматизации работы с инфраструктурой.</p>
26 <p>Рассмотрим, какие еще механики предлагает Terraform для передачи секретов.</p>
26 <p>Рассмотрим, какие еще механики предлагает Terraform для передачи секретов.</p>
27 <h2>Как передать секреты через командную строку</h2>
27 <h2>Как передать секреты через командную строку</h2>
28 <p>Чтобы не вводить секреты вручную поочередно, их можно передавать как дополнительные параметры -var при выполнении команд Terraform. В этом случае в параметре указываются имя и значение переменной, объявленной в Terraform:</p>
28 <p>Чтобы не вводить секреты вручную поочередно, их можно передавать как дополнительные параметры -var при выполнении команд Terraform. В этом случае в параметре указываются имя и значение переменной, объявленной в Terraform:</p>
29 <p>Чтобы не передавать секреты в открытом виде, мы можем использовать переменные окружения:</p>
29 <p>Чтобы не передавать секреты в открытом виде, мы можем использовать переменные окружения:</p>
30 <p>Если нужно передать Terraform несколько секретов, последовательно добавляем параметры -var для каждого отдельного секрета:</p>
30 <p>Если нужно передать Terraform несколько секретов, последовательно добавляем параметры -var для каждого отдельного секрета:</p>
31 <p>Такое решение уже можно автоматизировать. Но при передаче секретов по одному скрипты Terraform придется изменять при появлении новых -var.</p>
31 <p>Такое решение уже можно автоматизировать. Но при передаче секретов по одному скрипты Terraform придется изменять при появлении новых -var.</p>
32 <p>Также можно хранить переменные вида TF_VAR_* в environment сервера, с которого мы управляем инфраструктурой. Terraform распознает такие переменные, как адресованные ему. Это будет выглядеть так:</p>
32 <p>Также можно хранить переменные вида TF_VAR_* в environment сервера, с которого мы управляем инфраструктурой. Terraform распознает такие переменные, как адресованные ему. Это будет выглядеть так:</p>
33 <p>Такой способ удобен, так как экспортировать переменную нужно один раз. В этом случае в пределах текущей сессии терминала переменная будет передаваться всем командам Terraform.</p>
33 <p>Такой способ удобен, так как экспортировать переменную нужно один раз. В этом случае в пределах текущей сессии терминала переменная будет передаваться всем командам Terraform.</p>
34 <p>В некоторых случаях переменных окружения будет достаточно для работы с инфраструктурой Terraform. Но этот подход управления секретами может запутывать. В моменте мы не сможем сказать однозначно, с какими секретами работаем, пока не просмотрим их значения в окружении.</p>
34 <p>В некоторых случаях переменных окружения будет достаточно для работы с инфраструктурой Terraform. Но этот подход управления секретами может запутывать. В моменте мы не сможем сказать однозначно, с какими секретами работаем, пока не просмотрим их значения в окружении.</p>
35 <p>Чтобы получить больший контроль над секретами и их применением, посмотрим в сторону файлов.</p>
35 <p>Чтобы получить больший контроль над секретами и их применением, посмотрим в сторону файлов.</p>
36 <h2>Как хранить секреты в файле</h2>
36 <h2>Как хранить секреты в файле</h2>
37 <p>Чтобы хранить секреты, часто используется файл переменных окружения .env в корне проекта. В нем описываются необходимые приложению параметры, секреты, пароли и ключи.</p>
37 <p>Чтобы хранить секреты, часто используется файл переменных окружения .env в корне проекта. В нем описываются необходимые приложению параметры, секреты, пароли и ключи.</p>
38 <p>Terraform пока не поддерживает работу с файлами переменных окружения. Например, мы можем положить в проект с Terraform файл .env с таким содержимым:</p>
38 <p>Terraform пока не поддерживает работу с файлами переменных окружения. Например, мы можем положить в проект с Terraform файл .env с таким содержимым:</p>
39 <p>Terraform не увидит этот файл. Но он умеет похожим образом подключать файлы с переменными в форматах .tfvars или .tfvars.json.</p>
39 <p>Terraform не увидит этот файл. Но он умеет похожим образом подключать файлы с переменными в форматах .tfvars или .tfvars.json.</p>
40 <p>Сохраним наши чувствительные данные в отдельный файл с расширением .tfvars:</p>
40 <p>Сохраним наши чувствительные данные в отдельный файл с расширением .tfvars:</p>
41 <p>Назовем этот файл secret.tfvars и добавим в директорию с проектом Terraform. Далее его можно будет подключить при выполнении команд Terraform через параметр -var-file:</p>
41 <p>Назовем этот файл secret.tfvars и добавим в директорию с проектом Terraform. Далее его можно будет подключить при выполнении команд Terraform через параметр -var-file:</p>
42 <p>Все переменные, описанные в файле, будут переданы инфраструктуре Terraform.</p>
42 <p>Все переменные, описанные в файле, будут переданы инфраструктуре Terraform.</p>
43 <p>Terraform позволяет подключить несколько файлов одновременно. Мы можем разнести секреты по разным файлам. Это будет зависеть от их целевого назначения или от того, на какое окружение разворачиваем инфраструктуру.</p>
43 <p>Terraform позволяет подключить несколько файлов одновременно. Мы можем разнести секреты по разным файлам. Это будет зависеть от их целевого назначения или от того, на какое окружение разворачиваем инфраструктуру.</p>
44 <p>Например, вынесем из созданного ранее secret.tfvars секреты базы данных в отдельный файл и назовем его secret.db.tfvars:</p>
44 <p>Например, вынесем из созданного ранее secret.tfvars секреты базы данных в отдельный файл и назовем его secret.db.tfvars:</p>
45 <p><strong>secret.tfvars</strong></p>
45 <p><strong>secret.tfvars</strong></p>
46 <p><strong>secret.db.tfvars</strong></p>
46 <p><strong>secret.db.tfvars</strong></p>
47 <p>Попробуем подключить два файла сразу:</p>
47 <p>Попробуем подключить два файла сразу:</p>
48 <p>Результат будет таким же, как при использовании единого файла. Terraform получит значения из всех подключенных файлов.</p>
48 <p>Результат будет таким же, как при использовании единого файла. Terraform получит значения из всех подключенных файлов.</p>
49 <p>Это можно использовать для уменьшения дублирования кода. К примеру, вы пользуетесь одним облаком и используете один токен для всех своих проектов Terraform. В таком случае секреты облака можно хранить в отдельном файле и подключать этот файл ко всем своим проектам.</p>
49 <p>Это можно использовать для уменьшения дублирования кода. К примеру, вы пользуетесь одним облаком и используете один токен для всех своих проектов Terraform. В таком случае секреты облака можно хранить в отдельном файле и подключать этот файл ко всем своим проектам.</p>
50 <p>Что еще дает хранение секретов в .tfvars:</p>
50 <p>Что еще дает хранение секретов в .tfvars:</p>
51 <ul><li>В .tfvars можно описывать переменные спискового и объектного типа</li>
51 <ul><li>В .tfvars можно описывать переменные спискового и объектного типа</li>
52 <li>Они подчиняются приоритизации переменных Terraform</li>
52 <li>Они подчиняются приоритизации переменных Terraform</li>
53 <li>Есть вспомогательные инструменты, которые позволяют хранить такие файлы с секретами в зашифрованном виде</li>
53 <li>Есть вспомогательные инструменты, которые позволяют хранить такие файлы с секретами в зашифрованном виде</li>
54 </ul><p>Файлы с секретами и обычными переменными можно сохранять с именем вида *.auto.tfvars. Такие файлы не нужно явно подключать через -var-file - Terraform при выполнении команд будет подгружать их автоматически, если они находятся в директории Terraform.</p>
54 </ul><p>Файлы с секретами и обычными переменными можно сохранять с именем вида *.auto.tfvars. Такие файлы не нужно явно подключать через -var-file - Terraform при выполнении команд будет подгружать их автоматически, если они находятся в директории Terraform.</p>
55 <p>Хранение секретов в файлах может поставить под вопрос их безопасность. Мы должны хранить файлы с секретами так, чтобы они не попали к постороннему.</p>
55 <p>Хранение секретов в файлах может поставить под вопрос их безопасность. Мы должны хранить файлы с секретами так, чтобы они не попали к постороннему.</p>
56 <h2>Как защитить секреты от утечки</h2>
56 <h2>Как защитить секреты от утечки</h2>
57 <p>Любые файлы, в которых мы можем хранить незашифрованные секреты, нужно надежно защитить от утечки в сеть. Если мы храним проект с инфраструктурой в Git, важно случайно не добавить файл с секретами в коммит и отправить его в удаленный репозиторий.</p>
57 <p>Любые файлы, в которых мы можем хранить незашифрованные секреты, нужно надежно защитить от утечки в сеть. Если мы храним проект с инфраструктурой в Git, важно случайно не добавить файл с секретами в коммит и отправить его в удаленный репозиторий.</p>
58 <p>Стоит сразу определить, как именовать секретные файлы Terraform, и добавить соответствующую маску в файл .gitignore проекта. Для примеров выше подойдет маска secret.*. Любые файлы, которые начинаются с secret., будут игнорироваться Git, в том числе наши файлы secret.tfvars и secret.db.tfvars. Они будут храниться только у нас на машине либо в удаленном защищенном менеджере ключей.</p>
58 <p>Стоит сразу определить, как именовать секретные файлы Terraform, и добавить соответствующую маску в файл .gitignore проекта. Для примеров выше подойдет маска secret.*. Любые файлы, которые начинаются с secret., будут игнорироваться Git, в том числе наши файлы secret.tfvars и secret.db.tfvars. Они будут храниться только у нас на машине либо в удаленном защищенном менеджере ключей.</p>
59 <p>Еще нужно уделить внимание файлу состояния инфраструктуры - tfstate. По умолчанию tfstate сохраняется локально и содержит поля всех созданных в инфраструктуре ресурсов.</p>
59 <p>Еще нужно уделить внимание файлу состояния инфраструктуры - tfstate. По умолчанию tfstate сохраняется локально и содержит поля всех созданных в инфраструктуре ресурсов.</p>
60 <p>Создадим инфраструктуру с секретными полями:</p>
60 <p>Создадим инфраструктуру с секретными полями:</p>
61 <p>Теперь посмотрим, что сохранится в tfstate:</p>
61 <p>Теперь посмотрим, что сохранится в tfstate:</p>
62 <p>В tfstate все секретные параметры ресурсов хранятся в открытом виде независимо от их свойства sensitive. Такой tfstate позволяет получить адрес базы данных, а также логин и пароль ее владельца.</p>
62 <p>В tfstate все секретные параметры ресурсов хранятся в открытом виде независимо от их свойства sensitive. Такой tfstate позволяет получить адрес базы данных, а также логин и пароль ее владельца.</p>
63 <p>Получается, что любые файлы состояния тоже нужно игнорировать в Git, если мы хотим защитить доступ к нашим ресурсам.</p>
63 <p>Получается, что любые файлы состояния тоже нужно игнорировать в Git, если мы хотим защитить доступ к нашим ресурсам.</p>
64 <p>Чтобы в удаленный репозиторий не попало ничего секретного, .gitignore в проекте с Terraform должен выглядеть примерно так:</p>
64 <p>Чтобы в удаленный репозиторий не попало ничего секретного, .gitignore в проекте с Terraform должен выглядеть примерно так:</p>
65 <p>secret.* *.tfstate *.tfstate.*</p>
65 <p>secret.* *.tfstate *.tfstate.*</p>
66 <p>Игнорирование .tfstate ограничит возможность управлять инфраструктурой с разных машин, так как состояние инфраструктуры будет храниться только там, где мы ее создали. Позже мы найдем решение этой проблемы, когда познакомимся с удаленными бэкендами Terraform.</p>
66 <p>Игнорирование .tfstate ограничит возможность управлять инфраструктурой с разных машин, так как состояние инфраструктуры будет храниться только там, где мы ее создали. Позже мы найдем решение этой проблемы, когда познакомимся с удаленными бэкендами Terraform.</p>
67 <h2>Выводы</h2>
67 <h2>Выводы</h2>
68 <p>Любые переменные, значения которых потенциально могут давать доступ к нашей инфраструктуре или данным, следует интерпретировать как секреты. Такие переменные нужно объявлять с параметром sensitive = true, чтобы ограничить их отображение в консоли Terraform.</p>
68 <p>Любые переменные, значения которых потенциально могут давать доступ к нашей инфраструктуре или данным, следует интерпретировать как секреты. Такие переменные нужно объявлять с параметром sensitive = true, чтобы ограничить их отображение в консоли Terraform.</p>
69 <p>Секреты можно передавать через окружение с помощью экспорта в него переменных, которые начинаются на TF_VAR_*. Также секреты можно хранить в проекте в отдельных файлах формата .tfvars.</p>
69 <p>Секреты можно передавать через окружение с помощью экспорта в него переменных, которые начинаются на TF_VAR_*. Также секреты можно хранить в проекте в отдельных файлах формата .tfvars.</p>
70 <p>Нужно позаботиться, чтобы файлы с секретами не попали в публичные репозитории. Для этого любые секретные файлы с переменными, а также файлы *.tfstate, которые содержат параметры ресурсов Terraform в явном виде, нужно добавить в .gitignore проекта.</p>
70 <p>Нужно позаботиться, чтобы файлы с секретами не попали в публичные репозитории. Для этого любые секретные файлы с переменными, а также файлы *.tfstate, которые содержат параметры ресурсов Terraform в явном виде, нужно добавить в .gitignore проекта.</p>