Files
tf_provider/docs/ops/API_TOKENS.md
T

8.8 KiB
Raw Blame History

API Token Saga — 30.06.2026

Дата: 30 июня 2026 Контекст: попытка доступа к Nubes Cloud API для правки Terraform Provider


Кратко

6 часов debug'а. DDoS-Guard резал запросы, выдавая 403 Forbidden. Причина: User-Agent фильтрация + протухшие токены + неправильный endpoint.


Хронология ошибок

Ошибка 1: 403 от DDoS-Guard (2 часа потеряно)

$ curl https://deck-api.ngcloud.ru/api/v1/index.cfm/services/90
→ 403 Forbidden

Что думали: DDoS-Guard блокирует наш IP, нужно добавлять в whitelist. Проверяли с ВМ, из подов кластера — везде 403.

Реальная причина: DDoS-Guard фильтрует по User-Agent. curl/8.x блокируется, браузерный Mozilla/5.0 ... пропускается.

Как нашли: HAR-файлы (HAR/OK.har) показали что успешные запросы из браузера идут с HTTP/2 и браузерным User-Agent. Провайдер форсит HTTP/1.1 с Go-шным UA.

Фикс:

# НЕ работает:
curl https://deck-api.ngcloud.ru/...

# РАБОТАЕТ:
curl -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
     https://deck-api.ngcloud.ru/...

Ошибка 2: Старые токены без token_type (30 минут)

$ curl -H "Authorization: Bearer $OLD_TOKEN" ... (с правильным UA)
→ {"message":"invalid JWT token type"}

Что думали: Токены протухли. Проверили — живые (exp: август-сентябрь 2026). Потом думали что API изменился и требует новый формат.

Реальная причина: Старые токены из secrets/prod.token и secrets/dev.token были выданы БЕЗ поля token_type в JWT. API обновился и теперь требует token_type: "tech".

Декодирование старого токена:

{
  "iss": "auth-api",
  "sub": "0199e325-1cdf-7cda-9319-e5302a85e291",
  "exp": 1786932260,
  // token_type: ОТСУТСТВУЕТ ← причина ошибки
}

Ошибка 3: Токен не того стенда (30 минут)

$ curl -H "Authorization: Bearer $TEST_TOKEN" https://deck-api.ngcloud.ru/...
→ {"message":"IAM error"}

Что думали: Токен битый, неправильная подпись.

Реальная причина: Токены привязаны к конкретному API-endpoint. TEST-токен работает только на deck-api-test.ngcloud.ru, PROD — на deck-api.ngcloud.ru, DEV — на deck-api-dev.ngcloud.ru.


Ошибка 4: Двойной сбой (1 час)

На prod.token была комбинация двух проблем:

  1. Старый формат (без token_type) → "invalid JWT token type"
  2. Плюс DDoS-Guard скрывал реальный ответ API за 403 Forbidden

Пока не добавили User-Agent, мы даже не видели сообщение "invalid JWT token type" — видели только 403.


Как это работает (правильная схема)

1. API endpoints

Стенд Endpoint Токен
PROD https://deck-api.ngcloud.ru/api/v1/index.cfm secrets/prod.token
TEST https://deck-api-test.ngcloud.ru/api/v1/index.cfm secrets/test.token
DEV https://deck-api-dev.ngcloud.ru/api/v1/index.cfm secrets/dev.token

Токены НЕ взаимозаменяемы между стендами.

2. Аутентификация

┌──────────┐     Bearer JWT      ┌───────────┐     validate     ┌──────────┐
│  Client  │ ──────────────────→ │  deck-api  │ ──────────────→ │ auth-api │
│ (curl/Go)│ ←── JSON response ─ │ (CFML)     │ ←── OK/FAIL ── │ (IAM)    │
└──────────┘                     └───────────┘                  └──────────┘
  • Токен передаётся как Authorization: Bearer <JWT>
  • deck-api проверяет токен через auth-api (внутренний вызов)
  • JWT содержит: iss: "auth-api", token_type: "tech", ClientID: "WZ03709"
  • token_type обязателен (новое требование API)

3. User-Agent фильтрация DDoS-Guard

┌──────────┐                    ┌────────────┐                    ┌──────────┐
│  Client  │ ─── HTTP request → │ DDoS-Guard │ ─── if UA ok ───→ │ deck-api │
│          │ ←── 403 если UA ── │ 185.178... │                    │          │
│          │     не браузерный   └────────────┘                    └──────────┘

DDoS-Guard проверяет заголовок User-Agent:

  • curl/x.y.z403 Forbidden (блокировка)
  • Go-http-client/x.y403 Forbidden (провайдер блокируется!)
  • Mozilla/5.0 ...пропускается

Это критический баг провайдера: Go HTTP-клиент по умолчанию отправляет Go-http-client/2.0, который DDoS-Guard режет.

4. Правильный curl-запрос

# Рабочий запрос к PROD API:
curl -sk --max-time 10 \
  -H "Authorization: Bearer $(cat secrets/prod.token)" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
  "https://deck-api.ngcloud.ru/api/v1/index.cfm/services/90"

# Аналогично для TEST:
curl -sk --max-time 10 \
  -H "Authorization: Bearer $(cat secrets/test.token.new)" \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
  "https://deck-api-test.ngcloud.ru/api/v1/index.cfm/services/90"

5. Живые токены (30.06.2026)

Файл Назначение Выдан Истекает token_type ClientID
secrets/prod.token PROD 18.02.2026 17.08.2026 отсутствует
secrets/dev.token DEV 26.03.2026 22.09.2026 отсутствует
secrets/test.token TEST 14.03.2026 10.09.2026 отсутствует
secrets/test.token.new TEST 30.06.2026 13:37 ~дек.2026 "tech" WZ03709
secrets/dev.token.new (в памяти) DEV 30.06.2026 13:42 ~дек.2026 "tech" WZ03709
secrets/prod.token.new (в памяти) PROD 30.06.2026 13:41 ~дек.2026 "tech" WZ03709

⚠️ Новые токены ещё не сохранены в файлы secrets/ — только test сохранён.


Что надо исправить в провайдере

P0: User-Agent

В universal_rebuild/internal/core/client.gointernal/core/client.go Legacy):

// Сейчас (БАГ):
req.Header.Set("User-Agent", "Go-http-client/2.0")  // или default

// Надо:
req.Header.Set("User-Agent", "Terraform-Provider-Nubes/5.0")  // пропускаемый UA

Или в http.Client.Transport, или в каждом doRequest.

Связанное: HTTP/2

Провайдер форсит HTTP/1.1:

NextProtos: []string{"http/1.1"},
ForceAttemptHTTP2: false,

HAR показывает что API работает через HTTP/2. Возможно стоит разрешить HTTP/2 (убрать ForceAttemptHTTP2: false) — это ускорит поллинг.


Ключевые файлы

  • /home/naeel/tf_provider/HAR/OK.har — эталонные запросы (HTTP/2 + браузерный UA)
  • /home/naeel/tf_provider/secrets/prod.token — старый prod-токен (без token_type)
  • /home/naeel/tf_provider/secrets/test.token.new — новый test-токен (рабочий)
  • /home/naeel/tf_provider/devops/profiles/*/profile.env — endpoint'ы стендов
  • /home/naeel/tf_provider/universal_rebuild/internal/core/client.godoRequest() (надо править UA)
  • /home/naeel/tf_provider/universal_rebuild/internal/provider/provider.go — HTTP-транспорт (HTTP/1.1 force)