Бесплатная миграция IT-инфраструктуры в облако

Шифрование секретов в Hashicorp Terraform

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

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

Почему нельзя хранить чувствительную информацию в виде текста

Пользователи Terraform иногда сталкиваются с необходимостью обработать чувствительную информацию. Например, API-ключи или логин и пароль пользователя для БД.

Вот пример кода для создания базы данных в Timeweb Cloud (более подробный гайд о работе с Terraform и Timeweb Cloud размещён на GitHub):

resource "twc_db_mysql_8" 'my_db' {
name = "mysql_8_database'

     # Имя пользователя и пароль
     login = <To be decided>
     password = <To be decided>

     preset_id = data.twc_db_preset.example-db-preset.id
}

Чтобы код работал, в переменных «username» и «password» необходимо указать имя пользователя и пароль. Также наша задача — надежно обработать эти учетные данные и предотвратить их случайное раскрытие. 

Самый простой вариант — сразу присвоить переменным текстовые значения:

resource "twc_db_mysql_8" 'my_db' {
     name = "mysql_8_database'

     # Имя пользователя и пароль
     login = "root"
     password = "admin"

     preset_id = data.twc_db_preset.example-db-preset.id
}

Но это плохой путь, который вредит информационной безопасности всей системы, даже если вы используете частный репозиторий Git для хранения проекта. Дело в том, что любой пользователь с доступом к системе контроля версий также будет иметь доступ к секретам. 

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

В общем, хранение конфиденциальной информации в виде обычного текста сильно упрощает доступ к ним, чем, например, могут воспользоваться злоумышленники. Что, в целом, актуально для любых инструментов, а не только Terraform. Поэтому главное правило шифрования секретов в инфраструктуре как код — это хранение конфиденциальной информации не в виде открытого текста.

К чему могут привести незащищенная информация:

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

Файл состояния terraform.tfstate

У Terraform есть один изъян, который снижает безопасность системы. Каждый раз, когда пользователь использует Terraform для развёртки своей инфраструктуры, он сохраняет большое количество информации о ней, в том числе и предоставленные параметры для подключения к базе данных, в файле состояния terraform.tfstate в виде обычного текста. Этот файл сохраняется в той директории, в которой пользователь выполнял команду apply.  

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

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

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

Переменные окружения для шифрованию ключей

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

variable "username" {
     description = "Имя пользователя"  
     type = string
     sensitive = true


variable "password" {
     description = "Пароль пользователя"  
     type = string
     sensitive = true
}

Параметр type определяет тип переменных, а параметр sensitive помечает, что в переменной хранится конфиденциальная информация. Когда его значение равно true, данные переменной не отразятся в логах, в том числе при выполнении команд plan и apply.

Теперь заменим в коде resources переменные:

resource "twc_db_mysql_8" 'my_db' {
     name = "mysql_8_database'

     # Имя пользователя и пароль
     login = var.username
     password = var.password

     preset_id = data.twc_db_preset.example-db-preset.id
}

И установим значение переменных через терминал. В терминале к их имени необходимо добавлять TF_VAR_: usernameTF_VAR_username

export TF_VAR_username="root"
export TF_VAR_password="admin"

Когда пользователь выполнит команду terraform apply, Terraform будет использовать значение переменных среды. 

Важно: после выполнения Bash-команды сохраняются в истории. Чтобы в ней не сохранились конфиденциальные данные, такие как пароль и логин, воспользуйтесь переменной окружения HISTCONTROL. Задайте ей значение ignorespace — в таком случае команды, которые начинаются с пробела, сохранятся в истории не будут:

export HISTCONTROL=ignorespace

Шифрование конфиденциальных данных в Terraform с помощью GPG

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

Популярный подход к решению этой проблемы — это хранение конфиденциальных данных в виде зашифрованных файлов с помощью GPG. Для этого можно использовать для этого можно использовать «чистый» GPG, а можно воспользоваться менеджером паролей, который реализует такую же логику. Например, Pass. 

Менеджер паролей Pass

В нём данные хранятся в виде GPG-зашифрованных файлов. Они организованы в виде иерархии каталогов, которые могут быть скопированы с одного устройства на другое, а управлять Pass можно с помощью стандартных команд терминала.

Руководство по установке инструмента на разные операционные системы размещено на его официальном сайте. Вот код для инсталляции на Ubuntu:

sudo apt update
sudo apt install pass

Для работы с Pass понадобится GPG-ключ. Для его генерации в первую очередь необходимо установить GPG:

sudo apt install gpg

После — сгенерировать ключ:

gpg --full-generate-key

Выберите размер ключа и его тип (например «RSA and RSA»), а также укажите данные для генерации. После генерации в выводе терминала будет GPG-ключ:

Image1

Скопируйте GPG-ключ и используйте его для инициализации Pass:

pass init <GPG-ключ>

Зашифруем с помощью Pass уже упомянутые переменные — username и password:

pass insert username

После выполнения дважды введите значение переменной. Аналогичным образом поступаем с «password»:

pass insert password

Чтобы получить доступ к секретам из командной строки, используйте команду pass и имя секрета:

pass username

Введите кодовую фразу, которую указали при генерации GPG-ключа, и секрет будет отображен в консоли в виде обычного текста.

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

export TF_VAR_username=$(pass username)
export TF_VAR_password=$(pass password)

В чём плюсы и минусы использовать для шифрования секретов переменные окружения:

Плюсы

Минусы

Секреты остаются вне кода, а значит, не отражаются в репозитории.

Инфраструктура не полностью описывается в коде Terraform — это усложняет его поддержку и снижает читаемость.

Легко использовать: для начала работы не требуется высокой квалификации.

Требуются дополнительные шаги для работы с таким решением.

Переменные окружения можно интегрировать со многими менеджерами паролей, как в примере с Pass.

Поскольку вся работа с секретами происходит за пределами Terraform, на неё не распространяется средства безопасности, заложенные в коде.

Подходит для тестовых запусков: в качестве переменных окружения легко установить фиктивные значения.

 

Шифрование секретов с помощью HashiCorp Vault

Vault — это внешнее хранилище с открытым исходным кодом для хранения чувствительной информации. Его также, как и Terraform, разработала компания HashiCorp. 

Vault позволяет реализовать централизованное зашифрованное хранилище для секретов. Вот его ключевые функции:

  • Хранение чувствительной информации. Базовая функция Vault — шифрование и хранение секретов: паролей, API-ключей, сертификатов, токенов и других данных.
  • Аутентификация пользователей. Для получения доступа к секретам пользователь или приложение должен аутентифицироваться. В инструменте поддержано несколько методов: от классической связки пароля и логина до интеграции с другими система аутентификации.
  • Контроль доступа. В Vault можно гибко настроить, какие пользователи и приложения могут иметь доступ к тем или иным секретам. Это реализуется через политики доступа, в которых описываются разрешения на просмотр и другие операции с секретами.
  • Аудит запросов. С помощью инструмента можно отслеживать, кто и когда обращался к данным в хранилище.

Установка

Vault — это внешнее хранилище, и взаимодействие с ним осуществляется через сеть. Поэтому его можно установить как на локальное устройство и обращаться к нему через localhost, либо на удалённый сервер.

В этом материале расскажем, как установить его на Ubuntu:

  1. Обновите индексы пакетов и установите GPG.
sudo apt update && sudo apt install gpg
  1. Загрузите GPG-ключ. Для загрузки необходимо воспользоваться нероссийским IP-адресом.
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
  1. Установите Vault:
sudo apt update && sudo apt install vault
  1. Чтобы убедиться, что установка прошла успешно, проверьте версию программного обеспечения:
vault version

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

Настройка

После установки инструмент необходимо настроить. Мы будем использовать его в режиме сервера. Запустим его:

vault server -dev

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

Во время выполнения команды в терминале будет отображаться детали её прогресса, а после — URL-адрес, на котором работает сервер, и токен для авторизации. К нему можно подключиться даже через браузер, введя в поисковой строке URL-адрес сервера.

Для дальнейшей работы с сервером в режиме разработки необходимо создать переменную окружения с его URL-адресом. Если вы устанавливали Vault на локальном компьютере, то команда будет выглядеть так:

export VAULT_ADDR='http://127.0.0.1:8200'

Проверить состояние хранилища можно следующим образом:

vault status

Команда вернёт информацию о нём: дата создания, версию программного обеспечения и другое.

Для хранения конфиденциальной информации воспользуемся хранилищем «ключ-значение». Для начала создадим его:

vault secrets enable -path=db_data kv

После добавим в хранилище секреты:

vault kv put db_data/secret_tf username=root password=admin

Проверить результат можно прямо в браузере.

Как использовать HashiCorp Vault для хранения секретов в Terraform

В Main-файле Terraform укажем Vault как провайдера:

terraform {
     required_providers {
          vault = {
               source = "hashicorp/vault"
               version = "3.23.0"
          }

          twc = {
               source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"
          }
     }

     required_version = ">= 0.13"
}

В конфигурационном файле Terraform также необходимо прописать инструмент как провайдера:

provider "vault" {
 address = "http://127.0.0.1:8200"
 token   = "Токен Vault"
}

А также реализовать метод для чтения данных из хранилища:

data "vault_generic_secret" "secret_credentials" {
     path = "db_data/secret_tf"
}

resource "twc_db_mysql_8" 'my_db' {
     name = "mysql_8_database'

     # Имя пользователя и пароль
     login = data.vault_generic_secret.secret_credentials.data["username"]
     password = data.vault_generic_secret.secret_credentials.data["password"]

     preset_id = data.twc_db_preset.example-db-preset.id
}

Как автоматизировать шифрование секретов в Terraform

Шифрование секретов в Terraform можно автоматизировать, чтобы обеспечить масштабируемый и безопасный процесс управления конфиденциальными данными. Ниже — некоторые способы автоматизации:

  • Скрипты. С помощью них можно автоматически передавать секреты Terraform. Это можно реализовать с помощью GPG или OpenSSL.
  • CI/CD инструменты. Во многие CI/CD инструменты, например GitLab CI/CD или Jenkins, встроено шифрование, которое можно использовать в автоматическом режиме вместе с Terraform.

Заключение

В этой статье мы рассмотрели вопрос безопасности чувствительной информации, к чему может привести её хранение в незащищенном виде, обсудили, почему нужно бережно хранить файл состояния, а также привели примеры шифрования секретов в Terraform с помощью Hashicorp Vault, переменных сред и GPG.

Была ли статья полезна?
Ваша оценка очень важна
Пока нет комментариев