API Manager
API Manager
Section titled “API Manager”API Manager (Fastify 5) se stará o generování, šifrování, ukládání a rotaci API tokenů pro komunikaci mezi microservices.
Microservices potřebují bezpečné tokeny pro vzájemnou autentizaci. API Manager poskytuje:
- Centralizované úložiště tokenů — jediný zdroj pravdy
- Šifrování at-rest — AES-256-GCM s per-record náhodnou solí
- Auto-rotaci — automatický refresh cyklus každých 7 dní
- Rate limiting — 100 požadavků/15 min na IP
- Admin endpointy — status, manuální rotate/revoke, vynucená rotace
Port a přístup
Section titled “Port a přístup”- Port: 3200
- Health:
GET /health - Interní URL:
http://api-manager:3200 - Framework: Fastify
^5.9.0(migrace z Fastify 4 kvůli remediaci CVE — viz CHANGELOG) - Runtime: Node.js
>=20.0.0
Životní cyklus tokenu
Section titled “Životní cyklus tokenu”Získání tokenu
Section titled “Získání tokenu”GET /v1/token/:serviceX-Service-Secret: <SERVICE_SECRET>API Manager postupuje takto:
- Vyhledá
:servicev šifrovaném/datavolume - Pokud token existuje a je mladší než 7 dní → vrátí ho (z cache)
- Pokud chybí nebo je expirovaný → zavolá Strapi admin API pro vygenerování nového tokenu
- Zašifruje token pomocí AES-256-GCM
- Uloží do
/data/tokens/:service.enc - Vrátí volajícímu plaintext token
Úložiště tokenů
Section titled “Úložiště tokenů”/data/├── tokens/│ ├── git-connector.enc│ ├── cloud-connector.enc│ └── webhook-publisher.encKaždý zašifrovaný soubor tokenu je jeden řetězec se 4 hex segmenty oddělenými dvojtečkou — viz Detaily šifrování níže.
Auto-rotace
Section titled “Auto-rotace”Každých 7 dní (konfigurovatelné):
Cron job (běží každých 6 hodin, kontroluje expiraci) → Pro každý token: pokud stáří > 7 dní → Vyžádá nový token ze Strapi → Zašifruje + uloží → Pokračuje v obsluze nového tokenuManuální rotace
Section titled “Manuální rotace”curl -X POST http://api-manager:3200/v1/admin/rotate/git-connector \ -H "X-Admin-Key: <ADMIN_KEY>"
# Odpověď: { "success": true, "message": "Token rotated for git-connector (local)", "data": { ... } }Konfigurace
Section titled “Konfigurace”.env proměnné — dvě vrstvy:
API Manager samotný čte pouze proměnnou ENCRYPTION_KEY (viz api-manager/.env.example) — jeho kód nezná žádný název s prefixem API_MANAGER_. Orchestrační vrstva definuje stejný secret jako API_MANAGER_ENCRYPTION_KEY v orchestration/.env.example a docker-compose.core.yml ho do kontejneru mapuje jako obyčejné ENCRYPTION_KEY:
environment: - ENCRYPTION_KEY=${API_MANAGER_ENCRYPTION_KEY}Při nastavování klíče tedy editujte API_MANAGER_ENCRYPTION_KEY v orchestration/.env (orchestrační název); pokud spouštíte api-manager samostatně (mimo orchestraci, přes vlastní .env), nastavte přímo ENCRYPTION_KEY.
# Orchestrační název (orchestration/.env)API_MANAGER_ENCRYPTION_KEY=<base64-32-bytes>
# In-process název, který čte kód api-manageru (api-manager/.env, standalone dev)ENCRYPTION_KEY=<base64-32-bytes>
# Admin API klíč pro admin/* endpointyADMIN_API_KEY=<random-secret>
# Service secrets (jeden na konzumenta)SERVICE_SECRET_GIT_CONNECTOR=<secret>SERVICE_SECRET_CLOUD_CONNECTOR=<secret>SERVICE_SECRET_WEBHOOK_PUBLISHER=<secret>
# Strapi backend (per konfigurovaný region, např. "local")STRAPI_BACKEND_local_URL=<strapi-url>STRAPI_BACKEND_local_ADMIN_EMAIL=admin@sencai.spaceSTRAPI_BACKEND_local_ADMIN_PASSWORD=<password>Interval rotace a další per-service nastavení (např. rotationDays) se konfigurují per service v src/config/services/*.json, nikoliv jako jedna globální .env hodnota.
Autentizace mezi službami
Section titled “Autentizace mezi službami”Všechny interní požadavky používají hlavičku X-Service-Secret:
curl -H "X-Service-Secret: SERVICE_SECRET_GIT_CONNECTOR" \ http://api-manager:3200/v1/token/git-connectorEndpointy
Section titled “Endpointy”Routy jsou verzované pod /v1/ (F3.API.01). Legacy neverzované cesty /api/ stále fungují jako deprecated aliasy — každá odpověď na těchto cestách nese hlavičku Sunset (RFC 8594) a hlavičku Link: <.../v1/...>; rel="successor-version" odkazující na /v1 nástupce. Každá odpověď pod /v1/* i /api/* navíc nese X-API-Version: 1.
Endpoint pro získání tokenu
Section titled “Endpoint pro získání tokenu”GET /v1/token/:serviceHeaders: X-Service-Secret: <service-secret>
Response:{ "success": true, "data": { "token": "eyJ...", "expiresAt": "2026-04-26T12:00:00Z", "region": "local", "strapiBackendUrl": "http://backend:1337" }}Health check
Section titled “Health check”GET /health
Response:{ "status": "up", "timestamp": "2024-01-01T12:00:00Z"}Rotace tokenu (admin)
Section titled “Rotace tokenu (admin)”POST /v1/admin/rotate/:serviceHeaders: X-Admin-Key: <admin-key>
Response:{ "success": true, "message": "Token rotated for git-connector (local)", "data": { "serviceName": "git-connector", "region": "local", "rotatedAt": "2026-04-26T12:00:00Z", "expiresAt": "2026-05-03T12:00:00Z" }}Zneplatnění tokenu (admin)
Section titled “Zneplatnění tokenu (admin)”POST /v1/admin/revoke/:serviceHeaders: X-Admin-Key: <admin-key>
Response:{ "success": true, "message": "Token revoked for git-connector (local)"}Stav (admin)
Section titled “Stav (admin)”GET /v1/admin/statusHeaders: X-Admin-Key: <admin-key>
Response:{ "success": true, "data": { "tokens": [ { "serviceName": "git-connector", "region": "local", "createdAt": "...", "expiresAt": "...", "rotatedAt": "..." } ], "stats": { ... }, "rotator": { ... } }}Vynucená kontrola rotace (admin)
Section titled “Vynucená kontrola rotace (admin)”POST /v1/admin/force-rotationHeaders: X-Admin-Key: <admin-key>
Response:{ "success": true, "message": "Rotation check completed"}Příklad přes curl:
curl -X POST http://api-manager:3200/v1/admin/force-rotation \ -H "X-Admin-Key: <ADMIN_KEY>"Detaily šifrování
Section titled “Detaily šifrování”Algoritmus: AES-256-GCM, klíč odvozený přes crypto.scryptSync(masterKey, salt, 32)
Velikost klíče: 256 bitů (32 bajtů)
Velikost IV: 128 bitů (16 bajtů)
Velikost auth tagu: 128 bitů (16 bajtů)
Aktuální formát (v2) — per-record náhodná sůl:
iv(hex):authTag(hex):ciphertext(hex):salt(hex)Každé volání šifrování vygeneruje čerstvou náhodnou 16bajtovou sůl, která se uloží spolu se šifrovaným textem (4 hex segmenty oddělené dvojtečkou) a použije se pro odvození per-record klíče přes scrypt. Tím se nahradil starší fixní formát, který odvozoval klíč z jediné statické soli sdílené všemi tokeny — bezpečnostní oprava zdokumentovaná v CHANGELOG.md služby.
Legacy formát (v1) — zpětná kompatibilita jen pro dešifrování:
iv(hex):authTag(hex):ciphertext(hex)Starší tokeny se 3 segmenty (bez uložené soli) se stále korektně dešifrují pádem zpět na legacy statickou sůl. Nové šifrování vždy zapisuje 4segmentový formát; 3segmentový formát se od teď již nikdy nezapisuje.
Rate limiting
Section titled “Rate limiting”API Manager vynucuje rate limity:
- Limit: 100 požadavků
- Okno: 15 minut
- Podle: IP adresy
Odpověď při překročení limitu:
{ "statusCode": 429, "error": "Too Many Requests", "message": "Rate limit exceeded. Try again in 15 minutes."}Troubleshooting
Section titled “Troubleshooting”Q: „401 Unauthorized” při získávání tokenu
A: Hlavička X-Service-Secret chybí nebo neodpovídá SERVICE_SECRET_* v .env.
Q: „Token generation failed”
A: Strapi admin API může být nedostupné. Zkontrolujte:
- Že Strapi běží (
docker logs backend) - Že
STRAPI_BACKEND_local_ADMIN_EMAILaSTRAPI_BACKEND_local_ADMIN_PASSWORDjsou správně - Síťovou konektivitu ke Strapi
Q: Nelze dešifrovat tokeny
A: Nesoulad ENCRYPTION_KEY (in-process) / API_MANAGER_ENCRYPTION_KEY (orchestrace). Ujistěte se, že klíč zůstává konzistentní napříč restarty i napříč oběma vrstvami.
Q: Rotace nikdy neproběhne
A: Zkontrolujte logy (docker logs api-manager). Ověřte, že běží rotační cron a že je Strapi dostupné.