Создание сервера Vault от Hashicorp с помощью Packer и Terraform в DigitalOcean

Автор выбрал фонд Free and Open Source Fund для получения пожертвования в рамках программы Write for DOnations.

Введение

Vault от Hashicorp — это инструмент с открытым исходным кодом, предназначенный для безопасного хранения секретов и конфиденциальных данных в динамических облачных средах. Он обеспечивает надежное шифрование данных, доступ на основе идентификации с помощью настраиваемых политик, возможность предоставления в аренду и аннулирования секретов, а также подробный журнал аудита, который поддерживается в любой момент времени. Также Vault содержит HTTP API, что делает его идеальным решением для хранения учетных данных при использовании распределенного сервисно-ориентированного развертывания, например, Kubernetes.

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

В этом обучающем модуле вы научитесь использовать Packer для создания неизменяемого снимка системы с установленным Vault, а также сможете организовать его развертывание с помощью Terraform. В результате вы получите автоматизированную систему для развертывания Vault, что позволит сосредоточиться непосредственно на работе с Vault, а не на процессе установки и выделения ресурсов.

Предварительные требования

  • Packer, установленный на локальном компьютере. Для получения инструкций по установке ознакомьтесь с официальной документацией.
  • Terraform, установленный на локальном компьютере. Дополнительную информацию можно найти в официальной документации.
  • Персональный токен доступа (ключ API) с правами на чтение и запись для вашей учетной записи DigitalOcean. Чтобы узнать, как получить этот токен, ознакомьтесь со статьей Создание персонального токена доступа в документации.
  • Ключ SSH, который вы будете использовать для аутентификации с развернутыми дроплетами Vault, доступный на локальном компьютере и добавленный для вашей учетной записи DigitalOcean. Также вам потребуется его отпечаток, который вы можете скопировать на странице Безопасность вашей учетной записи, после его добавления. Ознакомьтесь с документацией DigitalOcean для получения подробных инструкций или с руководством Настройка ключей SSH.

Шаг 1 — Создание шаблона Packer

На данном шаге вы создадите файл конфигурации Packer с именем template, который будет указывать Packer, как следует собирать образ, который содержит предустановленный Vault. Вы будете использовать файл в формате JSON, широко используемый человекочитаемый формат файла конфигурации.

Для целей настоящего обучающего модуля все файлы следует хранить в каталоге ~/vault-orchestration. Создайте директорию, запустив следующую команду:

  • mkdir ~/vault-orchestration

Перейдите в директорию:

  • cd ~/vault-orchestration

Вы будете хранить файлы конфигурации для Packer и Terraform отдельно в разных поддиректориях. Создайте файлы с помощью следующей команды:

  • mkdir packer terraform

Поскольку сначала мы будем работать с Packer, перейдите в его директорию:

  • cd packer

Использование переменных шаблона

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

Мы будем хранить их в подкаталоге packer в файле с именем variables.json. Создайте его с помощью текстового редактора:

  • nano variables.json

Добавьте следующие строки:

~/vault-orchestration/packer/variables.json

{     "do_token": "your_do_api_key",     "base_system_image": "ubuntu-18-04-x64",     "region": "nyc3",     "size": "s-1vcpu-1gb" } 

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

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

Создание средств для сборки и поставщиков

После подготовки файла переменных вы сможете самостоятельно создать шаблон Packer.

Шаблон Packer для Vault хранится в файле с именем template.json. Создайте его с помощью текстового редактора:

  • nano template.json

Добавьте следующие строки:

~/vault-orchestration/packer/template.json

{      "builders": [{          "type": "digitalocean",          "api_token": "{{user `do_token`}}",          "image": "{{user `base_system_image`}}",          "region": "{{user `region`}}",          "size": "{{user `size`}}",          "ssh_username": "root"      }],      "provisioners": [{          "type": "shell",          "inline": [              "sleep 30",              "sudo apt-get update",              "sudo apt-get install unzip -y",              "curl -L https://releases.hashicorp.com/vault/1.3.2/vault_1.3.2_linux_amd64.zip -o vault.zip",              "unzip vault.zip",              "sudo chown root:root vault",              "mv vault /usr/local/bin/",              "rm -f vault.zip"          ]     }] } 

В шаблоне задаются массивы средств для сборки и поставщиков. Средства сборки указывают Packer, как выполнять сбор образа системы (в зависимости от типа) и где его хранить, а поставщики содержат набор действий, которые Packer должен выполнять для системы, прежде чем преобразовывать ее в неизменяемый образ, например, установка или настройка ПО. Без поставщиков вы получите нетронутый образ базовой системы. Как средства сборки, так и поставщики предоставляют параметры для дальнейшей настройки рабочего процесса.

Сначала вы задаете единое средство сборки типа digitalocean, что значит, что при необходимости создания образа Packer будет использовать предоставленные параметры для создания временного дроплета определенного размера с помощью предоставленного ключа API, который содержит заданный образ базовой системы и указанный регион. Формат для получения переменной — {{user 'variable_name'}}​​​, где выделенная часть является именем.

После предоставления временного дроплета поставщик будет подключаться к нему с помощью SSH с указанным именем пользователя и будет последовательно выполнять все указанные меры перед созданием снимка DigitalOcean Snapshot из дроплета и удалением последнего.

Он имеет тип shell, который будет выполнять определенные команды для цели. Команды могут быть указаны как внутри в виде массива строк или определены в отдельных файлах скриптов, если их включение в шаблон будет затруднено из-за большого размера. Команды в шаблоне будут 30 секунд ждать загрузки системы, а затем будут загружать и распаковать Vault 1.3.2. Проверьте официальную страницу загрузки Vault и замените ссылку в командах на самую последнюю версию для Linux, если таковая существует.

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

Чтобы подтвердить валидность шаблона, запустите следующую команду:

  • packer validate -var-file=variables.json template.json

Packer принимает путь к файлу переменных с помощью аргумента -var-file.

Вывод должен выглядеть так:

OutputTemplate validated successfully. 

При получении ошибки Packer будет указывать точное место возникновения ошибки, поэтому вы сможете устранить ее.

Теперь у вас есть рабочий шаблон, который позволяет получить образ с установленным Vault, а ключ API и прочие параметры определены в отдельном файле. Теперь вы готовы к вызову Packer и сборке снимка.

Шаг 2 — Сборка снимка

На данном шаге вы выполните сборку снимка DigitalOcean из вашего шаблона с помощью команды build в Packer.

Чтобы выполнить сборку снимка, запустите следующую команду:

  • packer build -var-file=variables.json template.json

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

Outputdigitalocean: output will be in this color.  ==> digitalocean: Creating temporary ssh key for droplet... ==> digitalocean: Creating droplet... ==> digitalocean: Waiting for droplet to become active... ==> digitalocean: Using ssh communicator to connect: ... ==> digitalocean: Waiting for SSH to become available... ==> digitalocean: Connected to SSH! ==> digitalocean: Provisioning with shell script: /tmp/packer-shell035430322 ... ==> digitalocean:   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current ==> digitalocean:                                  Dload  Upload   Total   Spent    Left  Speed     digitalocean: Archive:  vault.zip ==> digitalocean: 100 45.5M  100 45.5M    0     0   154M      0 --:--:-- --:--:-- --:--:--  153M     digitalocean:   inflating: vault ==> digitalocean: Gracefully shutting down droplet... ==> digitalocean: Creating snapshot: packer-1581537927 ==> digitalocean: Waiting for snapshot to complete... ==> digitalocean: Destroying droplet... ==> digitalocean: Deleting temporary ssh key... Build 'digitalocean' finished.  ==> Builds finished. The artifacts of successful builds are: --> digitalocean: A snapshot was created: 'packer-1581537927' (ID: 58230938) in regions '...' 

Packer фиксирует в журнале все шаги в процессе сборки шаблона. Последняя строка содержит имя снимка (например, packer-1581537927), а также его идентификатор в скобках, выделенный красным. Запишите ваш идентификатор снимка, поскольку он потребуется на следующем шаге.

Если процесс сборки не удалось завершить из-за ошибок API, подождите несколько минут и повторите попытку.

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

Шаг 3 — Создание конфигурации Terraform

На данном шаге вы создадите конфигурацию Terraform для автоматизации развертываний дроплетов снимка с установленным Vault, который вы только что создали с помощью Packer.

Перед созданием реальной конфигурации Terraform для развертывания Vault из ранее собранного снимка вам потребуется настроить для него поставщика DigitalOcean. Перейдите в подкаталог terraform с помощью следующей команды:

  • cd ~/vault-orchestration/terraform

Затем создайте файл с именем do-provider.tf, где будет храниться поставщик:

  • nano do-provider.tf

Добавьте следующие строки:

~/vault-orchestration/terraform/do-provider.tf

variable "do_token" { }  variable "ssh_fingerprint" { }  variable "instance_count" {   default = "1" }  variable "do_snapshot_id" { }  variable "do_name" {   default = "vault" }  variable "do_region" { }  variable "do_size" { }  variable "do_private_networking" {   default = true }  provider "digitalocean" {   token = var.do_token } 

В этом файле объявляются переменные параметров и предоставляется поставщик digitalocean с ключом API. Позднее вы будете использовать эти переменные в шаблоне Terraform, но сначала вам потребуется задать их значения. Для таких целей Terraform поддерживает указание значений переменных в файле определений переменных, как и Packer. Имя файла должно заканчиваться на .tfvars или .tfvars.json. Позже вы передадите этот файл в Terraform с помощью аргумента -var-file.

Сохраните и закройте файл.

Создайте файл определений переменных с именем definitions.tfvars с помощью текстового редактора:

  • nano definitions.tfvars

Добавьте следующие строки:

~/vault-orchestration/terraform/definitions.tf

do_token         = "your_do_api_key" ssh_fingerprint  = "your_ssh_key_fingerprint" do_snapshot_id   = your_do_snapshot_id do_name          = "vault" do_region        = "nyc3" do_size          = "s-1vcpu-1gb" instance_count   = 1 

Не забудьте заменить your_do_api_key, your_ssh_key_fingerprint и your_do_snapshot_id на ваш ключ API, отпечаток вашего ключа SSH и идентификатор снимка, который вы записали на предыдущем шаге. Параметры do_region и do_size должны иметь те же значения, что и в файле переменных Packer. Если вам потребуется выполнить развертывание сразу нескольких экземпляров, измените значение instance_count на желаемое.

После завершения редактирования сохраните и закройте файл.

Дополнительную информацию по поставщику DigitalOcean Terraform можно найти в официальной документации.

Вы будете хранить конфигурацию развертывания снимка с Vault в файле deployment.tf в директории terraform. Создайте его с помощью текстового редактора:

  • nano deployment.tf

Добавьте следующие строки:

~/vault-orchestration/terraform/deployment.tf

resource "digitalocean_droplet" "vault" {   count              = var.instance_count   image              = var.do_snapshot_id   name               = var.do_name   region             = var.do_region   size               = var.do_size   private_networking = var.do_private_networking   ssh_keys = [     var.ssh_fingerprint   ] }  output "instance_ip_addr" {   value = {     for instance in digitalocean_droplet.vault:     instance.id => instance.ipv4_address   }   description = "The IP addresses of the deployed instances, paired with their IDs." } 

Здесь вы определяете единый ресурс типа digitalocean_droplet с именем vault. Затем вы задаете параметры в соответствии со значениями переменных и добавляете ключ SSH (с помощью его отпечатка) из вашей учетной записи DigitalOcean в ресурс дроплета. Наконец, вы выводите IP-адреса всех вновь развернутых экземпляров в консоль.

Сохраните и закройте файл.

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

  • terraform init

Вывод должен выглядеть так:

Output Initializing the backend...  Initializing provider plugins...  The following providers do not have any version constraints in configuration, so the latest version was installed.  To prevent automatic upgrades to new major versions that may contain breaking changes, it is recommended to add version = "..." constraints to the corresponding provider blocks in configuration, with the constraint strings suggested below.  * provider.digitalocean: version = "~> 1.14"  Terraform has been successfully initialized!  You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work.  If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary. 

При инициализации каталога как проекта Terraform считывает доступные файлы конфигурации и загружает необходимые плагины, как показано в выводе.

Теперь у вас есть конфигурация Terraform для развертывания вашего снимка Vault. Теперь вы можете перейти к его проверке и развертыванию в дроплете.

Шаг 4 — Развертывание Vault с помощью Terraform

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

Запустите следующую команду для проверки вашей конфигурации:

  • terraform validate

Вывод должен выглядеть так:

OutputSuccess! The configuration is valid. 

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

  • terraform plan -var-file="definitions.tfvars"

Terraform принимает файл определений переменных с помощью параметра -var-file.

Результат будет выглядеть примерно следующим образом:

OutputRefreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage.   ------------------------------------------------------------------------  An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols:   + create  Terraform will perform the following actions:    # digitalocean_droplet.vault[0] will be created   + resource "digitalocean_droplet" "vault" {         ...     }  Plan: 1 to add, 0 to change, 0 to destroy.  ------------------------------------------------------------------------  Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run. 

Зеленый знак + в начале строки resource "digitalocean_droplet" "vault" означает, что Terraform будет создавать новый дроплет с именем vault, используя следующие параметры. Это правильно, поэтому теперь вы можете воспользоваться командой terraform apply:

  • terraform apply -var-file="definitions.tfvars"

Введите yes при запросе. Через несколько минут дроплет завершит предоставление ресурсов, а вы увидите примерно следующее:

OutputAn execution plan has been generated and is shown below. Resource actions are indicated with the following symbols:   + create  Terraform will perform the following actions:    + digitalocean_droplet.vault-droplet  ...  Plan: 1 to add, 0 to change, 0 to destroy.  ...  digitalocean_droplet.vault-droplet: Creating...  ...  Apply complete! Resources: 1 added, 0 changed, 0 destroyed.  Outputs:  instance_ip_addr = {   "181254240" = "your_new_server_ip" } 

На экране результатов Terraform показывает выполненные действия (в нашем случае — для создания дроплета) и отображает свой публичный IP-адрес в конце. Вы будете использовать его для подключения к вашему новому дроплету в следующем шаге.

Вы создали новый дроплет из снимка с Vault и теперь можете проверить его.

Шаг 5 — Проверка вашего развернутого дроплета

На данном шаге вы получите доступ к вашему новому дроплету с помощью SSH и убедитесь, что Vault установлен корректно.

Если вы используете Windows, вы можете использовать программные продукты Kitty или Putty для подключения к дроплету с ключом SSH.

На компьютерах Linux и macOS вы можете использовать уже имеющуюся команду ssh для подключения:

Введите yes при запросе. После входа запустите Vault с помощью следующей команды:

  • vault

:

OutputUsage: vault <command> [args]  Common commands:     read        Read data and retrieves secrets     write       Write data, configuration, and secrets     delete      Delete secrets and configuration     list        List data or secrets     login       Authenticate locally     agent       Start a Vault agent     server      Start a Vault server     status      Print seal and HA status     unwrap      Unwrap a wrapped secret  Other commands:     audit          Interact with audit devices     auth           Interact with auth methods     debug          Runs the debug command     kv             Interact with Vault's Key-Value storage     lease          Interact with leases     namespace      Interact with namespaces     operator       Perform operator-specific tasks     path-help      Retrieve API help for paths     plugin         Interact with Vault plugins and catalog     policy         Interact with policies     print          Prints runtime configurations     secrets        Interact with secrets engines     ssh            Initiate an SSH session     token          Interact with tokens 

Подключение можно закрыть с помощью команды exit.

Теперь вы убедились, что недавно развернутый дроплет был создан из полученного снимка, а Vault установлен корректно.

Заключение

Вы создали автоматизированную систему для развертывания Hashicorp Vault в дроплетах DigitalOcean с помощью Terraform и Packer. Теперь вы можете развернуть необходимое вам количество серверов Vault. Для начала использования Vault вам потребуется инициализировать его и выполнить настройку. Соответствующие инструкции можно найти в официальной документации.

Дополнительные обучающие материалы по работе с Terraform можно найти на странице материалов по Terraform.