mirror of
https://github.com/fosrl/pangolin.git
synced 2026-08-14 08:19:51 +02:00
optionally stamp ip header for downstream use
This commit is contained in:
@@ -12,6 +12,15 @@ export const AI_GATEWAY_RESOURCE_TYPE_HEADER =
|
||||
|
||||
export type AiGatewayResourceType = "resource" | "site-resource";
|
||||
|
||||
// Opt-in (server.enable_ai_gateway_client_ip_header): carries the client IP
|
||||
// that Badger resolved at the Traefik hop, so it survives an intermediary
|
||||
// proxy between Traefik and the AI gateway that overwrites
|
||||
// X-Forwarded-For/X-Real-Ip instead of appending to them. Set by a
|
||||
// disableForwardAuth Badger middleware instance (see getTraefikConfig.ts)
|
||||
// on the site-resource inference router only, since that's the sole path
|
||||
// that resolves request identity from the client IP.
|
||||
export const AI_GATEWAY_CLIENT_IP_HEADER = "X-Pangolin-Client-Ip";
|
||||
|
||||
/**
|
||||
* Derive a Traefik-injected trust token from the server secret.
|
||||
* Traefik overwrites this header on inference routes so the AI gateway can
|
||||
|
||||
@@ -153,6 +153,25 @@ export const configSchema = z
|
||||
})
|
||||
.optional(),
|
||||
trust_proxy: z.int().gte(0).optional().default(1),
|
||||
// Opt-in: have Traefik/Badger stamp the resolved client IP
|
||||
// into a dedicated header (X-Pangolin-Client-Ip) on the
|
||||
// site-resource AI gateway route, so it survives an
|
||||
// intermediary proxy between Traefik and the gateway that
|
||||
// overwrites X-Forwarded-For/X-Real-Ip instead of appending
|
||||
// to them. Off by default since it requires a Badger
|
||||
// version that supports realIpHeader.
|
||||
enable_ai_gateway_client_ip_header: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.default(false)
|
||||
.transform((val) =>
|
||||
process.env.ENABLE_AI_GATEWAY_CLIENT_IP_HEADER !==
|
||||
undefined
|
||||
? process.env
|
||||
.ENABLE_AI_GATEWAY_CLIENT_IP_HEADER ===
|
||||
"true"
|
||||
: val
|
||||
),
|
||||
secret: z.string().pipe(z.string().min(8)).optional(),
|
||||
maxmind_db_path: z.string().optional(),
|
||||
maxmind_asn_path: z.string().optional()
|
||||
@@ -183,7 +202,8 @@ export const configSchema = z
|
||||
"resource_session_request_param",
|
||||
dashboard_session_length_hours: 720,
|
||||
resource_session_length_hours: 720,
|
||||
trust_proxy: 1
|
||||
trust_proxy: 1,
|
||||
enable_ai_gateway_client_ip_header: false
|
||||
}),
|
||||
postgres: z
|
||||
.object({
|
||||
|
||||
@@ -27,6 +27,7 @@ import regionalCache from "@server/lib/cache";
|
||||
import {
|
||||
AI_GATEWAY_TRUST_HEADER,
|
||||
AI_GATEWAY_RESOURCE_TYPE_HEADER,
|
||||
AI_GATEWAY_CLIENT_IP_HEADER,
|
||||
getAiGatewayTrustToken
|
||||
} from "@server/lib/aiGatewayTrust";
|
||||
|
||||
@@ -786,6 +787,28 @@ export async function getTraefikConfig(
|
||||
}
|
||||
};
|
||||
|
||||
// Opt-in: a Badger instance with forward auth disabled, used only
|
||||
// to stamp the resolved client IP into a dedicated header before
|
||||
// the request reaches whatever sits between Traefik and the AI
|
||||
// gateway. Only the site-resource router below needs this - it's
|
||||
// the only path that resolves request identity from the client IP
|
||||
// (see resolveRequestUser in aiGateway/pipeline.ts) - and it's the
|
||||
// only inference router that doesn't already run Badger.
|
||||
const aiGatewayClientIpMiddlewareName = "ai-gateway-client-ip";
|
||||
const enableAiGatewayClientIpHeader =
|
||||
config.getRawConfig().server.enable_ai_gateway_client_ip_header;
|
||||
if (enableAiGatewayClientIpHeader) {
|
||||
config_output.http.middlewares[aiGatewayClientIpMiddlewareName] =
|
||||
{
|
||||
plugin: {
|
||||
badger: {
|
||||
disableForwardAuth: true,
|
||||
realIpHeader: AI_GATEWAY_CLIENT_IP_HEADER
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Public inference resources: same TLS/cert-resolver handling as
|
||||
// plain http-mode resources, but the service points at the AI
|
||||
// gateway instead of any real backend targets.
|
||||
@@ -958,6 +981,9 @@ export async function getTraefikConfig(
|
||||
const additionalMiddlewares =
|
||||
config.getRawConfig().traefik.additional_middlewares || [];
|
||||
const routerMiddlewares = [
|
||||
...(enableAiGatewayClientIpHeader
|
||||
? [aiGatewayClientIpMiddlewareName]
|
||||
: []),
|
||||
aiGatewayTrustMiddlewareNameSiteResource,
|
||||
srHeadersMiddlewareName,
|
||||
...additionalMiddlewares
|
||||
|
||||
Reference in New Issue
Block a user