Skip to main content

api-gateway (Kong) — Security Model

Status: populated Owner: TBD (Platform / SRE) Last updated: 2026-04-17 Companion: SERVICE_OVERVIEW · APPLICATION_LOGIC · 13 Security, Compliance & Tenancy · Service Template

1. Purpose

Kong is the platform's perimeter enforcement point. This document defines TLS posture, authentication, rate-limiting, IP controls, logging discipline, secrets, and the threat model at the edge.

2. TLS

ControlSetting
Inbound TLS1.2 minimum, 1.3 preferred
Cipher suitesModern per Mozilla "intermediate"; no RC4/3DES
Certificate sourceCloudflare origin certs for CF → Kong; Let's Encrypt (cert-manager) for direct origin; HSM-backed root for enterprise customers
HSTSIssued by Cloudflare (edge); Kong also sends Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Upstream TLS (Kong → service)mTLS on the cluster network preferred; plaintext acceptable only inside a cluster-private mesh
OCSP staplingEnabled
Cert rotationAutomated via cert-manager or Cloudflare; alert on <14 days to expiry

3. JWT authentication

  • Plugin: jwt.
  • Algorithms: RS256 only (asymmetric); HS256 explicitly disabled.
  • JWKS source: auth-service at https://internal.auth-service.svc/.well-known/jwks.json.
  • Cache: 5 min in-process; refresh on kid miss.
  • Claims validated at Kong:
ClaimCheck
isshttps://auth.ghasi.io (or env-equivalent)
audghasi-platform
expMust be > now
nbfIf present, must be ≤ now
iatMust be within 24 h
kidMust resolve in JWKS
tidMust be a non-empty string (Kong does not verify tenancy access — upstream does)

Kong enforces presence and signature; business authorization (scope, role, resource ACL) is enforced by upstream services.

4. API key authentication

  • Plugin: key-auth — validates presence and uniqueness of X-Api-Key.
  • Key storage: Hashed (SHA-256) in either Kong DB (DB mode) or, preferred, resolved at request-time by the custom ghasi-api-key-lookup plugin against auth-service.
  • Key format: opaque string, entropy ≥ 256 bits; prefixed gk_live_ / gk_test_ by auth-service convention.
  • Header stripping: X-Api-Key is not forwarded upstream.
  • Rotation: auth-service supports two active keys per account (old + new) during rotation; no Kong restart required when using the custom plugin (cache TTL 60 s).
  • Revocation: flagged in auth-service; plugin cache expires within 60 s; optional push-invalidation via a DELETE /cache/ghasi:apikey:<hash> admin call when immediate revocation is required.

5. IP allow/deny

  • Plugin: ip-restriction.
  • Admin routes (/admin/*): allow-list of SRE/ops CIDRs + corporate VPN egress.
  • Partner integration routes: allow-list of partner source IPs (configured per tenant in auth-service, surfaced to Kong via decK generation).
  • Global deny-list: known-bad sources (shared with Cloudflare; Cloudflare is the primary layer).

6. Header scrubbing and request transformation

  • Plugin: request-transformer (ingress) and response transformer for egress.
  • Strip inbound: X-Forwarded-Host (can be spoofed), server fingerprint headers.
  • Inject upstream: X-Gateway-Source: kong (so upstream can distinguish edge vs direct).
  • Strip outbound: Server, X-Powered-By, Via.

7. Bot detection

  • Plugin: bot-detection.
  • Blocks obvious bot user-agents on public routes (/v1/auth/login, /v1/webhooks/test).
  • Allows documented crawlers only where relevant (none, for the API).

8. Body logging policy

Body logging is globally disabled on all log sinks (http-log, datadog, file log). Rationale:

  • SMS message content is PII and telecom-regulated.
  • API keys might appear in body errors if upstream echoes them (defence in depth).
  • GDPR / regional privacy regulations forbid unnecessary retention of message content.

Only headers and metadata are logged (and even then Authorization / X-Api-Key values are redacted — only a presence flag is captured). See EVENT_SCHEMAS §3.

9. Rate limiting as a security control

Per-key and per-account limits (see APPLICATION_LOGIC §4) serve DoS resistance, credential stuffing resistance, and brute-force resistance:

ControlLimit
/v1/auth/login per-IP5/min (anti-credential-stuffing)
/v1/auth/login per-account10/15min (anti-lockout-bypass)
/v1/sms/send per-key10/s default (tier-dependent)
Global burst5 000 req/s (guardrail)

Failed-auth responses are rate-limited (Kong returns 429 after N failed attempts from same IP) to resist enumeration.

10. Secrets

SecretWhereRotation
JWT signing key (private)auth-service only; Kong never holds the private keyHandled by auth-service
JWKS (public)Pulled by Kong at runtimeAutomatic on cache expiry
TLS certificates (origin)cert-manager / Cloudflare90 d auto
Redis passwordKong vault (K8s Secret / Vault)Per SRE rotation policy
Custom plugin service token (Kong → auth-service)Kong vault, short-lived mTLS cert preferred30 d
Admin API tokenVault; CI-onlyPer CI policy

Secrets appear in decK YAML only as vault references ({vault://env/<name>}).

11. Audit events

Kong itself does not emit audit events (no domain concept). Audit-relevant edge events are derived from:

EventSource
Auth success / failureAccess logs (status + X-Api-Key-Id / JWT sub)
Admin API changeKong admin log (when DB mode) + decK sync PR in Git
Route/plugin changeGit commit history in ops/kong/
Rate-limit rejection stormPrometheus alert → on-call

12. Threat model

ThreatLikelihoodMitigation
Credential stuffing on /v1/auth/loginHighPer-IP rate limit, account lockout, Cloudflare Turnstile (optional at CF layer), bot-detection
API key leakage in logsMediumBody logging disabled; X-Api-Key stripped pre-log; only key ID in access logs
Expired / forged JWTMediumRS256 only; JWKS validated; aud/iss/exp checked
Account enumeration on /v1/accounts/*MediumUpstream normalises errors; Kong rate-limits per IP
DoS / floodHigh (public API)Global + per-key limits; Cloudflare WAF; Kong pod HPA
Header smuggling (spoofed X-Account-Id)LowUpstream only trusts when X-Gateway-Source: kong AND request arrived on internal net (mTLS / NetworkPolicy)
Admin API exposureLow (by design)NetworkPolicy + Kong listen on non-public interface; mTLS
Plugin supply-chainMediumPinned Kong versions; SBOM in CI; custom plugin code-reviewed
Route drift vs OpenAPIMediumCI lint (see TESTING_STRATEGY)

13. Tenant isolation

Kong does not enforce tenancy. It injects X-Account-Id / X-Tier from JWT or API-key resolution. Tenant isolation is enforced in upstream services via account_id scoping and PostgreSQL RLS (see 13 Security, Compliance & Tenancy).

14. GDPR / data privacy

Kong holds no personal data at rest. Access logs contain IP + UA, retained 14 d hot / 90 d archive, subject to the platform retention policy. GDPR erasure sagas do not touch Kong.

15. Open questions

  • mTLS between Kong and upstream services — required in production?
  • Cloudflare Turnstile (or equivalent bot challenge) on /v1/auth/login — at CF edge or pushed to Kong via a plugin?
  • Admin API authentication strategy — mTLS, short-lived OIDC tokens, both?