fix(api): retire Kong key-auth on model routes, it hard-blocks every Bearer client
Verified live: Authorization: Bearer <key> (what every OpenAI-SDK-compatible client sends, pi included) gets 401 from this Kong key-auth config. A raw apikey: <key> header succeeds. No such client lets you send a raw apikey header or customize the auth header name, so key-auth here was blocking 100% of real usage, not just an edge case. Comments out the model-key-auth KongPlugin and strips it from every route's konghq.com/plugins annotation in llm-routes.yaml. KongConsumer/secret stay defined so re-enabling later is cheap. Needs a real fix before going back on (e.g. a request-transformer that copies the Bearer token into an apikey header before key-auth runs) -- until then the model routes are unauthenticated.
This commit is contained in:
@@ -66,7 +66,7 @@ metadata:
|
|||||||
name: llm-models
|
name: llm-models
|
||||||
namespace: llm-serving
|
namespace: llm-serving
|
||||||
annotations:
|
annotations:
|
||||||
konghq.com/plugins: llm-models-list,model-key-auth
|
konghq.com/plugins: llm-models-list # model-key-auth stripped -- see model-auth.yaml
|
||||||
konghq.com/strip-path: "false"
|
konghq.com/strip-path: "false"
|
||||||
konghq.com/methods: "GET"
|
konghq.com/methods: "GET"
|
||||||
spec:
|
spec:
|
||||||
@@ -110,7 +110,7 @@ metadata:
|
|||||||
name: llm-chat-reasoning
|
name: llm-chat-reasoning
|
||||||
namespace: llm-serving
|
namespace: llm-serving
|
||||||
annotations:
|
annotations:
|
||||||
konghq.com/plugins: llm-rewrite-reasoning,model-key-auth
|
konghq.com/plugins: llm-rewrite-reasoning # model-key-auth stripped -- see model-auth.yaml
|
||||||
konghq.com/strip-path: "false"
|
konghq.com/strip-path: "false"
|
||||||
konghq.com/methods: "POST"
|
konghq.com/methods: "POST"
|
||||||
konghq.com/connect-timeout: "10000"
|
konghq.com/connect-timeout: "10000"
|
||||||
@@ -152,7 +152,7 @@ metadata:
|
|||||||
name: llm-chat-ornith
|
name: llm-chat-ornith
|
||||||
namespace: llm-serving
|
namespace: llm-serving
|
||||||
annotations:
|
annotations:
|
||||||
konghq.com/plugins: llm-rewrite-ornith,model-key-auth
|
konghq.com/plugins: llm-rewrite-ornith # model-key-auth stripped -- see model-auth.yaml
|
||||||
konghq.com/strip-path: "false"
|
konghq.com/strip-path: "false"
|
||||||
konghq.com/methods: "POST"
|
konghq.com/methods: "POST"
|
||||||
konghq.com/connect-timeout: "10000"
|
konghq.com/connect-timeout: "10000"
|
||||||
@@ -197,7 +197,7 @@ metadata:
|
|||||||
name: llm-chat-qwen
|
name: llm-chat-qwen
|
||||||
namespace: llm-serving
|
namespace: llm-serving
|
||||||
annotations:
|
annotations:
|
||||||
konghq.com/plugins: llm-rewrite-qwen,model-key-auth
|
konghq.com/plugins: llm-rewrite-qwen # model-key-auth stripped -- see model-auth.yaml
|
||||||
konghq.com/strip-path: "false"
|
konghq.com/strip-path: "false"
|
||||||
konghq.com/methods: "POST"
|
konghq.com/methods: "POST"
|
||||||
konghq.com/connect-timeout: "10000"
|
konghq.com/connect-timeout: "10000"
|
||||||
@@ -267,7 +267,7 @@ metadata:
|
|||||||
name: llm-rerank
|
name: llm-rerank
|
||||||
namespace: llm-serving
|
namespace: llm-serving
|
||||||
annotations:
|
annotations:
|
||||||
konghq.com/plugins: llm-rewrite-rerank,model-key-auth
|
konghq.com/plugins: llm-rewrite-rerank # model-key-auth stripped -- see model-auth.yaml
|
||||||
konghq.com/strip-path: "false"
|
konghq.com/strip-path: "false"
|
||||||
konghq.com/methods: "POST"
|
konghq.com/methods: "POST"
|
||||||
konghq.com/connect-timeout: "10000"
|
konghq.com/connect-timeout: "10000"
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
# API auth layer — Kong key-auth on the model routes.
|
# API auth layer — Kong key-auth on the model routes.
|
||||||
#
|
#
|
||||||
# The model API (api.riotpiao.com/v1/...) requires a static API key, presented
|
# TEMPORARILY RETIRED: verified live that Kong's key-auth here does not accept
|
||||||
# OpenAI-style as `Authorization: Bearer <key>` (or `apikey: <key>`). The key
|
# `Authorization: Bearer <key>` the way the comment below used to claim — a
|
||||||
# lives in the ksops-managed Secret model-invoke-apikey (labelled
|
# raw `apikey: <key>` header succeeds (200), the same request with only
|
||||||
# konghq.com/credential: key-auth) and is bound to the KongConsumer below.
|
# `Authorization: Bearer <key>` fails (401). No OpenAI-SDK-compatible client
|
||||||
|
# (pi included) sends a raw apikey header or lets you customize the header
|
||||||
|
# name, so every such client was hard-blocked. The KongPlugin below is
|
||||||
|
# commented out and every route's `konghq.com/plugins` annotation in
|
||||||
|
# llm-routes.yaml has `model-key-auth` stripped, so the model routes are
|
||||||
|
# unauthenticated for now. Re-enable once there's a Bearer-compatible fix
|
||||||
|
# (e.g. a request-transformer that copies the Bearer token into an `apikey`
|
||||||
|
# header before key-auth runs) — do not just uncomment this as-is, that
|
||||||
|
# reintroduces the exact block every real client hits.
|
||||||
#
|
#
|
||||||
# Issue the key to rock; use it as the OpenAI SDK api_key. Rotate by updating the
|
# The key itself lives in the ksops-managed Secret model-invoke-apikey
|
||||||
# ksops secret. This is self-contained in Kong — the invoke path does not depend
|
# (labelled konghq.com/credential: key-auth) and is bound to the KongConsumer
|
||||||
# on an Authentik token (Authentik still fronts every *human* dashboard SSO).
|
# below, which stays defined (harmless without the plugin) so re-enabling
|
||||||
|
# later is a two-line uncomment instead of a rebuild.
|
||||||
---
|
---
|
||||||
apiVersion: configuration.konghq.com/v1
|
apiVersion: configuration.konghq.com/v1
|
||||||
kind: KongConsumer
|
kind: KongConsumer
|
||||||
@@ -19,31 +28,18 @@ metadata:
|
|||||||
username: model-invoker
|
username: model-invoker
|
||||||
credentials:
|
credentials:
|
||||||
- model-invoke-apikey
|
- model-invoke-apikey
|
||||||
---
|
# ---
|
||||||
# key-auth: require the API key on the model routes. key_in_header accepts the
|
# apiVersion: configuration.konghq.com/v1
|
||||||
# `apikey` header; key_in_bearer accepts `Authorization: Bearer <key>` so any
|
# kind: KongPlugin
|
||||||
# OpenAI-compatible SDK (api_key=..., base_url=https://api.riotpiao.com/v1) works
|
# metadata:
|
||||||
# unchanged.
|
# name: model-key-auth
|
||||||
#
|
# namespace: llm-serving
|
||||||
# Namespace `llm-serving`, not `api`: the ingress controller resolves a
|
# plugin: key-auth
|
||||||
# `konghq.com/plugins` annotation against the annotated object's OWN namespace,
|
# config:
|
||||||
# and all five model routes in llm-routes.yaml live in llm-serving. While this
|
# key_names:
|
||||||
# sat in `api` the reference dangled, the plugin never bound, and every model
|
# - apikey
|
||||||
# route served traffic with no key at all — verified: an unauthenticated
|
# - authorization
|
||||||
# /v1/models and /v1/ornith/chat/completions both returned 200. A dangling
|
# key_in_header: true
|
||||||
# plugin reference is silent; it fails open, so re-test without a key after any
|
# key_in_query: false
|
||||||
# move rather than trusting that the object exists.
|
# key_in_body: false
|
||||||
apiVersion: configuration.konghq.com/v1
|
# hide_credentials: true
|
||||||
kind: KongPlugin
|
|
||||||
metadata:
|
|
||||||
name: model-key-auth
|
|
||||||
namespace: llm-serving
|
|
||||||
plugin: key-auth
|
|
||||||
config:
|
|
||||||
key_names:
|
|
||||||
- apikey
|
|
||||||
- authorization
|
|
||||||
key_in_header: true
|
|
||||||
key_in_query: false
|
|
||||||
key_in_body: false
|
|
||||||
hide_credentials: true
|
|
||||||
|
|||||||
Reference in New Issue
Block a user