Files
tf_provider/docs/ops/API_TOKENS.md
T

199 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.
**Фикс:**
```bash
# НЕ работает:
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"`.
**Декодирование старого токена:**
```json
{
"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.z`**403 Forbidden** (блокировка)
- `Go-http-client/x.y`**403 Forbidden** (провайдер блокируется!)
- `Mozilla/5.0 ...`**пропускается**
Это **критический баг провайдера**: Go HTTP-клиент по умолчанию отправляет `Go-http-client/2.0`, который DDoS-Guard режет.
### 4. Правильный curl-запрос
```bash
# Рабочий запрос к 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.go``internal/core/client.go` Legacy):
```go
// Сейчас (БАГ):
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:
```go
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.go``doRequest()` (надо править UA)
- `/home/naeel/tf_provider/universal_rebuild/internal/provider/provider.go` — HTTP-транспорт (HTTP/1.1 force)