6.6 KiB
Сценарий восстановления GPG ключей и починки Registry (28.01.2026)
Этот документ описывает последовательность действий, выполненных для исправления проблемы с верификацией GPG подписи Terraform провайдера nubes.
1. Проблема (Контекст)
При попытке выполнить terraform init клиент получал ошибку проверки сигнатуры.
Диагностика показала:
- Terraform Registry Server (на
registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru --> <!-- ⛔ LEGACY: registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru --> ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru -->) в своем коде (main.go) отдавал клиентам публичный GPG ключ с ID3534B7A1E185F2C1. - Приватный ключ для этого 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.
- Экспортирован публичный ключ:
gpg --armor --export BC2B32E138B12582 - Обновлен исходный код сервера
operator/cmd/registry/main.go:- Заменено значение поля
ASCIIArmorв структуреgpgKeyна новый блок ключа. - Обновлен
KeyID.
- Заменено значение поля
- Пересборка и деплой:
- Собран Docker образ:
naeel/terraform-registry-server:docs-dev. - Выполнен пуш в Docker Hub:
make push-registry. - Обновлен Deployment в K8s:
kubectl rollout restart deployment/registry-server -n terra.
- Собран Docker образ:
Шаг 3: Сборка и Подписание провайдера (Release Engineering)
Чтобы клиент (terraform init) принял провайдер, файлы должны лежать в S3 бакете и иметь корректную подпись.
- Сборка:
go build -o build_artifacts/terraform-provider-nubes_v1.0.0 . - Упаковка (ZIP):
Terraform требует определенного формата имени архива.
zip terraform-provider-nubes_1.0.0_linux_amd64.zip terraform-provider-nubes_v1.0.0 - Хеширование (SHA256SUMS):
sha256sum terraform-provider-nubes_1.0.0_linux_amd64.zip > terraform-provider-nubes_1.0.0_SHA256SUMS - Подписание (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
Загружены три обязательных файла в структуру директорий реестра (registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru -->/nubes/nubes/1.0.0/):
- Сам архив:
terraform-provider-nubes_1.0.0_linux_amd64.zip - Файл сумм:
terraform-provider-nubes_1.0.0_SHA256SUMS - Подпись сумм:
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 = "registry.kube5s.ru <!-- ⛔ LEGACY: registry.kube5s.ru ЗАКРЫТ. Актуальный хост: tf-registry.containerk8s.services.ngcloud.ru -->/nubes/nubes"
version = "1.0.0"
}
Лог terraform init:
Installed registry.kube5s.ru /nubes/nubes v1.0.0 (self-signed, key ID BC2B32E138B12582)
Функциональное тестирование
Был проведен полный цикл создания ресурсов через скачанный провайдер:
- Plan: Успешное планирование создания S3 бакета
terraform-registry-client-test-bucket-01. - Apply: Ресурс успешно создан в облаке Nubes (API вернул 200 OK, провайдер обработал ответ).
- Destroy: Ресурс успешно удален.
Это подтверждает, что цепочка Registry -> Signed Download -> Provider Execution -> Cloud API полностью работоспособна.
4. Бэкап ключей
Ключи сохранены локально в директории client_package (не для коммита в репозиторий, а как рабочий артефакт сессии):
public_key.ascprivate_key.asc