Skip to main content

🧑‍💻 Terraform-провайдер для Tuna

· 3 min read

Когда туннелей, доменов и шлюзов становится больше десятка, настраивать их кликами в личном кабинете уже неудобно: сложно повторить конфигурацию для второго окружения, непонятно, кто и когда что поменял. Поэтому мы выпустили Terraform-провайдер yuccastream/tuna — теперь инфраструктуру Tuna можно хранить в git рядом с остальным кодом, ревьюить в merge request'ах и применять через terraform apply.

terraform {
required_providers {
tuna = {
source = "yuccastream/tuna"
}
}
}

resource "tuna_domain" "preview" {
subdomain = "myapp-preview"
location = "ru"
}

Что можно описать​

РесурсЧто описывает
tuna_domainЗарезервированный домен: поддомен встроенной зоны, своей зоны или собственный домен
tuna_domain_zoneДоменная зона
tuna_tls_certificateTLS-сертификат для доменной зоны
tuna_gatewayШлюз с политикой трафика
tuna_endpointTCP-порт
tuna_ip_policy, tuna_ip_policy_ruleIP-политика и её правила
tuna_public_keyПубличный SSH-ключ
tuna_temporal_tokenВременный токен для запуска туннелей

Источник данных tuna_tunnels возвращает список туннелей аккаунта. Существующие ресурсы из личного кабинета можно подтянуть в state через terraform import.

Провайдер работает с Terraform 1.11+ и с OpenTofu. Приватный ключ TLS-сертификата передаётся через write-only атрибут и не попадает в state.

Пример: временные туннели для CI​

Типичный сценарий — preview-окружения в CI. Terraform резервирует домен и выпускает временный токен с ограничениями, а CI-задача поднимает туннель с этим токеном. Основной API-ключ в CI при этом не попадает:

resource "tuna_temporal_token" "ci" {
description = "CI preview"
duration = "24h"
allow_http = true
allow_tcp = false
limit_by_active_tunnels = 5
limit_by_created_tunnels = 100
}

output "ci_tunnel_token" {
value = tuna_temporal_token.ci.token
sensitive = true
}
terraform apply
export TUNA_TOKEN="$(terraform output -raw ci_tunnel_token)"
tuna http 8080 --subdomain=myapp-preview

Пример: шлюз с политикой из файла​

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

resource "tuna_domain" "api" {
subdomain = "myapp-api"
location = "ru"
}

resource "tuna_gateway" "api" {
domain_id = tuna_domain.api.id
policy = file("${path.module}/policy.yaml")
}

Ещё несколько сценариев — своя доменная зона с wildcard-сертификатом, доступ по IP только из офиса — есть в документации.

API-ключи с правами по продуктам​

Провайдеру нужен API-ключ, и отдавать ему полный доступ к аккаунту незачем. Поэтому вместе с провайдером API-ключи получили скоупы: ключ можно ограничить туннелями, мониторингом, секретами, бастионом, отчётами или командой — на чтение или на запись. Для Terraform достаточно tunnels:write.

Заодно мы закрыли для API-ключей всё, что может навредить аккаунту при утечке ключа:

  • выпуск новых API-ключей, приглашения в команду и смена ролей участников;
  • безопасность аккаунта: пароль, MFA, WebAuthn, токен туннелей, привязки провайдеров входа;
  • оплата и подписка: способ оплаты, смена тарифа, получатели счетов, удаление команды;
  • продление и завершение веб-сессий, пароли и mesh.

Всё это делается только из личного кабинета. Ключ, выпущенный без скоупов, получает доступ read_api — только на чтение.

С чего начать​

  1. Выпустите в личном кабинете API-ключ со скоупом tunnels:write.
  2. Передайте его провайдеру через export TUNA_API_KEY=....
  3. Опишите первый ресурс и выполните terraform init && terraform apply.

Справочник по всем ресурсам и атрибутам — в Terraform Registry, обзор и сценарии — в нашей документации. Это первая версия провайдера: если вам не хватает какого-то ресурса, напишите нам — расширим.

Leave feedback​

If you enjoy using Tuna, or on the contrary you are not happy with something, please leave feedback.

Help​

We value our users and carefully review every request. If you have any problems with tuna, please contact us in one of the following ways: