Files
tf_provider/docs/20_discovery/gpg_key_rotation_scenario.md
T
2026-06-30 15:45:24 +04:00

5.8 KiB

Сценарий восстановления GPG ключей и починки Registry (28.01.2026)

Этот документ описывает последовательность действий, выполненных для исправления проблемы с верификацией GPG подписи Terraform провайдера nubes.

1. Проблема (Контекст)

При попытке выполнить terraform init клиент получал ошибку проверки сигнатуры. Диагностика показала:

  • Terraform Registry Server (на terra.k8c.ru) в своем коде (main.go) отдавал клиентам публичный GPG ключ с ID 3534B7A1E185F2C1.
  • Приватный ключ для этого ID отсутствовал в окружении, поэтому новые сборки провайдера невозможно было подписать так, чтобы они прошли проверку этим ключом.
  • Реестр был "рассинхронизирован" с артефактами.

2. Реализованное решение

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

Шаг 1: Генерация новой пары ключей

Сгенерирован новый GPG ключ (EDDSA) для подписи релизов.

  • Key ID: BC2B32E138B12582
  • Fingerprint: B157380F7572A0BA8DF6F708BC2B32E138B12582
  • User ID: Nubes Terraform Provider <admin@nubes.ru>

Команда генерации:

gpg --batch --generate-key gpg-gen-key.conf

Шаг 2: Внедрение Публичного ключа в Registry Server

Публичная часть нового ключа (ASCII Armor) должна отдаваться сервером реестра по протоколу Terraform Registry Protocol.

  1. Экспортирован публичный ключ:
    gpg --armor --export BC2B32E138B12582
    
  2. Обновлен исходный код сервера operator/cmd/registry/main.go:
    • Заменено значение поля ASCIIArmor в структуре gpgKey на новый блок ключа.
    • Обновлен KeyID.
  3. Пересборка и деплой:
    • Собран Docker образ: naeel/terraform-registry-server:docs-dev.
    • Выполнен пуш в Docker Hub: make push-registry.
    • Обновлен Deployment в K8s: kubectl rollout restart deployment/registry-server -n terra.

Шаг 3: Сборка и Подписание провайдера (Release Engineering)

Чтобы клиент (terraform init) принял провайдер, файлы должны лежать в S3 бакете и иметь корректную подпись.

  1. Сборка:
    go build -o build_artifacts/terraform-provider-nubes_v1.0.0 .
    
  2. Упаковка (ZIP): Terraform требует определенного формата имени архива.
    zip terraform-provider-nubes_1.0.0_linux_amd64.zip terraform-provider-nubes_v1.0.0
    
  3. Хеширование (SHA256SUMS):
    sha256sum terraform-provider-nubes_1.0.0_linux_amd64.zip > terraform-provider-nubes_1.0.0_SHA256SUMS
    
  4. Подписание (Signature): Критически важно использовать бинарную (detached) подпись, а не ASCII armor, так как Terraform ожидает именно бинарный формат для .sig файла.
    gpg --batch --detach-sign --default-key BC2B32E138B12582 --output terraform-provider-nubes_1.0.0_SHA256SUMS.sig terraform-provider-nubes_1.0.0_SHA256SUMS
    

Шаг 4: Публикация в S3

Загружены три обязательных файла в структуру директорий реестра (terra.k8c.ru/nubes/nubes/1.0.0/):

  1. Сам архив: terraform-provider-nubes_1.0.0_linux_amd64.zip
  2. Файл сумм: terraform-provider-nubes_1.0.0_SHA256SUMS
  3. Подпись сумм: terraform-provider-nubes_1.0.0_SHA256SUMS.sig

Использовался mc cp (S3 client).

3. Итог и Верификация (End-to-End Test)

Инициализация

Проверка на "чистом" клиенте (client_package) без dev_overrides прошла успешно. Terraform скачал провайдер из приватного реестра и валидировал подпись.

provider "nubes" {
  source  = "terra.k8c.ru/nubes/nubes"
  version = "1.0.0"
}

Лог terraform init:

Installed terra.k8c.ru/nubes/nubes v1.0.0 (self-signed, key ID BC2B32E138B12582)

Функциональное тестирование

Был проведен полный цикл создания ресурсов через скачанный провайдер:

  1. Plan: Успешное планирование создания S3 бакета terraform-registry-client-test-bucket-01.
  2. Apply: Ресурс успешно создан в облаке Nubes (API вернул 200 OK, провайдер обработал ответ).
  3. Destroy: Ресурс успешно удален.

Это подтверждает, что цепочка Registry -> Signed Download -> Provider Execution -> Cloud API полностью работоспособна.

4. Бэкап ключей

Ключи сохранены локально в директории client_package (не для коммита в репозиторий, а как рабочий артефакт сессии):

  • public_key.asc
  • private_key.asc