Merge commit from fork

Signed-off-by: Jan Larwig <jan@larwig.com>
This commit is contained in:
Jan Larwig 2025-11-08 12:52:31 +01:00 committed by GitHub
parent 5993067505
commit f3f30fa976
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 40 additions and 1 deletions

View File

@ -266,6 +266,7 @@ response header.
| ----- | ---- | ----------- | | ----- | ---- | ----------- |
| `name` | _string_ | Name is the header name to be used for this set of values.<br/>Names should be unique within a list of Headers. | | `name` | _string_ | Name is the header name to be used for this set of values.<br/>Names should be unique within a list of Headers. |
| `preserveRequestValue` | _bool_ | PreserveRequestValue determines whether any values for this header<br/>should be preserved for the request to the upstream server.<br/>This option only applies to injected request headers.<br/>Defaults to false (headers that match this header will be stripped). | | `preserveRequestValue` | _bool_ | PreserveRequestValue determines whether any values for this header<br/>should be preserved for the request to the upstream server.<br/>This option only applies to injected request headers.<br/>Defaults to false (headers that match this header will be stripped). |
| `InsecureSkipHeaderNormalization` | _bool_ | InsecureSkipHeaderNormalization disables normalizing the header name<br/>According to RFC 7230 Section 3.2 there aren't any rules about<br/>capitalization of header names, but the standard practice is to use<br/>Title-Case (e.g. X-Forwarded-For). By default, header names will be<br/>normalized to Title-Case and any incoming headers that match will be<br/>treated as the same header. Additionally underscores (_) in header names<br/>will be converted to dashes (-) when normalizing.<br/>Defaults to false (header names will be normalized). |
| `values` | _[[]HeaderValue](#headervalue)_ | Values contains the desired values for this header | | `values` | _[[]HeaderValue](#headervalue)_ | Values contains the desired values for this header |
### HeaderValue ### HeaderValue

View File

@ -13,6 +13,16 @@ type Header struct {
// Defaults to false (headers that match this header will be stripped). // Defaults to false (headers that match this header will be stripped).
PreserveRequestValue bool `json:"preserveRequestValue,omitempty"` PreserveRequestValue bool `json:"preserveRequestValue,omitempty"`
// InsecureSkipHeaderNormalization disables normalizing the header name
// According to RFC 7230 Section 3.2 there aren't any rules about
// capitalization of header names, but the standard practice is to use
// Title-Case (e.g. X-Forwarded-For). By default, header names will be
// normalized to Title-Case and any incoming headers that match will be
// treated as the same header. Additionally underscores (_) in header names
// will be converted to dashes (-) when normalizing.
// Defaults to false (header names will be normalized).
InsecureSkipHeaderNormalization bool `json:"InsecureSkipHeaderNormalization,omitempty"`
// Values contains the desired values for this header // Values contains the desired values for this header
Values []HeaderValue `json:"values,omitempty"` Values []HeaderValue `json:"values,omitempty"`
} }

View File

@ -53,6 +53,11 @@ func flattenHeaders(headers http.Header) {
func stripHeaders(headers []options.Header, next http.Handler) http.Handler { func stripHeaders(headers []options.Header, next http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
for _, header := range headers { for _, header := range headers {
if header.InsecureSkipHeaderNormalization {
req.Header.Del(header.Name)
continue
}
stripNormalizedHeader(req, header) stripNormalizedHeader(req, header)
} }
next.ServeHTTP(rw, req) next.ServeHTTP(rw, req)

View File

@ -205,7 +205,7 @@ var _ = Describe("Headers Suite", func() {
expectedHeaders: nil, expectedHeaders: nil,
expectedErr: "error building request header injector: error building request injector: error building injector for header \"X-Auth-Request-Authorization\": error loading basicAuthPassword: secret source is invalid: exactly one entry required, specify either value, fromEnv or fromFile", expectedErr: "error building request header injector: error building request injector: error building injector for header \"X-Auth-Request-Authorization\": error loading basicAuthPassword: secret source is invalid: exactly one entry required, specify either value, fromEnv or fromFile",
}), }),
Entry("strips normalized variants before injecting (no preservation)", headersTableInput{ Entry("strips normalized variants before injecting", headersTableInput{
headers: []options.Header{ headers: []options.Header{
{ {
Name: "X-Auth-Request-User", Name: "X-Auth-Request-User",
@ -226,6 +226,29 @@ var _ = Describe("Headers Suite", func() {
}, },
expectedErr: "", expectedErr: "",
}), }),
Entry("doesn't strip normalized variants before injecting", headersTableInput{
headers: []options.Header{
{
Name: "X-Auth-Request-User",
InsecureSkipHeaderNormalization: true,
Values: []options.HeaderValue{
{
ClaimSource: &options.ClaimSource{Claim: "user"},
},
},
},
},
initialHeaders: http.Header{
"X-Auth-Request-User": []string{"old"},
"X-Auth_Request_User": []string{"evil"},
},
session: &sessionsapi.SessionState{User: "user-123"},
expectedHeaders: http.Header{
"X-Auth-Request-User": []string{"user-123"},
"X-Auth_Request_User": []string{"evil"},
},
expectedErr: "",
}),
) )
DescribeTable("the response header injector", DescribeTable("the response header injector",