mirror of
https://github.com/alibaba/higress.git
synced 2026-05-24 20:57:31 +08:00
fix(ai-proxy): re-anchor X-HI-ORIGINAL-AUTH on first hop to fix cascaded-gateway 401 (#3864)
Signed-off-by: jingze <daijingze.djz@alibaba-inc.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -158,10 +158,38 @@ func initContext(ctx wrapper.HttpContext) {
|
|||||||
for _, originHeader := range headerToOriginalHeaderMapping {
|
for _, originHeader := range headerToOriginalHeaderMapping {
|
||||||
_ = proxywasm.RemoveHttpRequestHeader(originHeader)
|
_ = proxywasm.RemoveHttpRequestHeader(originHeader)
|
||||||
}
|
}
|
||||||
originalAuth, _ := proxywasm.GetHttpRequestHeader(util.HeaderOriginalAuth)
|
|
||||||
if originalAuth == "" {
|
// Distinguish "first hop into this gateway" from "internal_redirect re-entry".
|
||||||
|
//
|
||||||
|
// Signal: x-higress-fallback-from. It is set by Envoy custom_response's
|
||||||
|
// RedirectPolicy on every internal_redirect within this gateway, and it
|
||||||
|
// survives mutateRequestHeaders on the redirected stream (it is NOT in
|
||||||
|
// Envoy's hardcoded strip list).
|
||||||
|
//
|
||||||
|
// Absence => first hop. Distrust any incoming X-HI-ORIGINAL-AUTH — it may
|
||||||
|
// have been set by a client or by an upstream cascaded gateway
|
||||||
|
// running its own ai-proxy. Re-anchor the saved value from the
|
||||||
|
// request's current Authorization, which is what this gateway
|
||||||
|
// should treat as the "original" credential for later
|
||||||
|
// internal_redirect hops.
|
||||||
|
// Presence => internal_redirect re-entry within this gateway. Leave
|
||||||
|
// X-HI-ORIGINAL-AUTH alone — it preserves the value this gateway's
|
||||||
|
// ai-proxy wrote on the previous pass, which key-auth needs for
|
||||||
|
// re-authentication after Authorization has been replaced with
|
||||||
|
// the upstream apiToken.
|
||||||
|
//
|
||||||
|
// SAFETY DEPENDENCY: this signal is reliable only when external callers
|
||||||
|
// cannot supply x-higress-fallback-from. For cascaded deployments where an
|
||||||
|
// upstream gateway may itself be in an internal_redirect chain when forwarding
|
||||||
|
// to this gateway, list x-higress-fallback-from (and x-hi-original-auth) in
|
||||||
|
// the HCM internal_only_headers as defense-in-depth.
|
||||||
|
fallbackFrom, _ := proxywasm.GetHttpRequestHeader(util.HeaderHigressFallbackFrom)
|
||||||
|
if fallbackFrom == "" {
|
||||||
|
_ = proxywasm.RemoveHttpRequestHeader(util.HeaderOriginalAuth)
|
||||||
value, _ := proxywasm.GetHttpRequestHeader(util.HeaderAuthorization)
|
value, _ := proxywasm.GetHttpRequestHeader(util.HeaderAuthorization)
|
||||||
ctx.SetContext(ctxOriginalAuth, value)
|
if value != "" {
|
||||||
|
ctx.SetContext(ctxOriginalAuth, value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,27 @@ const (
|
|||||||
HeaderOriginalHost = "X-ENVOY-ORIGINAL-HOST"
|
HeaderOriginalHost = "X-ENVOY-ORIGINAL-HOST"
|
||||||
HeaderOriginalAuth = "X-HI-ORIGINAL-AUTH"
|
HeaderOriginalAuth = "X-HI-ORIGINAL-AUTH"
|
||||||
|
|
||||||
|
// HeaderHigressFallbackFrom is set by Envoy custom_response's RedirectPolicy
|
||||||
|
// on internal_redirect (request_headers_to_add) and survives the redirect's
|
||||||
|
// mutateRequestHeaders pass (it is NOT in Envoy's hardcoded strip list). So
|
||||||
|
// its presence at the wasm boundary is a usable signal that the current
|
||||||
|
// filter-chain pass is an internal_redirect re-entry within this gateway.
|
||||||
|
//
|
||||||
|
// SAFETY DEPENDENCY: this header is NOT spoofing-proof unless the listener
|
||||||
|
// lists it in internal_only_headers. An upstream gateway that is itself in
|
||||||
|
// the middle of an internal_redirect chain may forward this header through
|
||||||
|
// to this gateway, causing this gateway's first hop to be misclassified as
|
||||||
|
// a re-entry. Operators relying on cascaded ai-proxy gateways should add
|
||||||
|
// `x-higress-fallback-from` and `x-hi-original-auth` to the listener's
|
||||||
|
// internal_only_headers list as defense-in-depth.
|
||||||
|
//
|
||||||
|
// Note: x-envoy-original-url (which Envoy sets on every internal_redirect
|
||||||
|
// in router.cc) is NOT usable here, because Envoy's recreateStream re-runs
|
||||||
|
// mutateRequestHeaders on the redirected stream and strips x-envoy-original-url
|
||||||
|
// from the hardcoded "headers to be stripped from edge AND intermediate-hop
|
||||||
|
// external requests" list — so wasm filters never see it on a redirect.
|
||||||
|
HeaderHigressFallbackFrom = "x-higress-fallback-from"
|
||||||
|
|
||||||
MimeTypeTextPlain = "text/plain"
|
MimeTypeTextPlain = "text/plain"
|
||||||
MimeTypeApplicationJson = "application/json"
|
MimeTypeApplicationJson = "application/json"
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user